Move SF trace logging into a separate thread
SF trace logging currently happens on the main thread, which affects
performance. Move it to a separate thread to mitigate the overhead.
Use a lock to prevent the drawing state to be updated while it is being
dumped.
Also, allow the buffer size for SF traces to be configured. Current buffer
size is fixed to 100MB, which is unfeasible for phones with lower resources.
Created option 1029 to manually update the buffer size.
To trigger the option use:
- adb shell su root service call SurfaceFlinger 1029 i32 <SIZE>
This option trigger an "Invalid Argument" error if it receives a
negative value.
Finally, just log Winscope trace if visible regions are dirty. SF
currently logs all Winscope frames. It should log only if there is a
change to mitigate resource consumption.
Test: Flash a device. Start a trace. Run systrace. Record a trace. Check
if the `commitTransaction` trace happens in a separate SF thread and
doesn't block the critical path
Change-Id: Ie05ad5c025a185b28209bbc5d26655ba9ff9042b
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index fd919af..a75ac61 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -18,30 +18,38 @@
#include <layerproto/LayerProtoHeader.h>
#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <android-base/thread_annotations.h>
+#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
+#include <thread>
using namespace android::surfaceflinger;
namespace android {
+class SurfaceFlinger;
+
constexpr auto operator""_MB(unsigned long long const num) {
return num * 1024 * 1024;
}
-
/*
* SurfaceTracing records layer states during surface flinging.
*/
class SurfaceTracing {
public:
- void enable() { enable(kDefaultBufferCapInByte); }
- void enable(size_t bufferSizeInByte);
- status_t disable();
- void traceLayers(const char* where, LayersProto);
-
+ SurfaceTracing(SurfaceFlinger& flinger) : mFlinger(flinger) {}
+ void enable();
+ bool disable();
+ status_t writeToFile();
bool isEnabled() const;
+ void notify(const char* where);
+
+ void setBufferSize(size_t bufferSizeInByte);
+ void writeToFileAsync();
void dump(std::string& result) const;
private:
@@ -54,6 +62,7 @@
size_t used() const { return mUsedInBytes; }
size_t frameCount() const { return mStorage.size(); }
+ void setSize(size_t newSize) { mSizeInBytes = newSize; }
void reset(size_t newSize);
void emplace(LayersTraceProto&& proto);
void flush(LayersTraceFileProto* fileProto);
@@ -64,11 +73,23 @@
std::queue<LayersTraceProto> mStorage;
};
- status_t writeProtoFileLocked();
+ void mainLoop();
+ void traceLayers(const char* where);
+ LayersTraceProto traceLayersLocked(const char* where);
+ void writeProtoFileLocked() REQUIRES(mTraceLock);
- bool mEnabled = false;
- mutable std::mutex mTraceMutex;
- LayersTraceBuffer mBuffer;
+ const SurfaceFlinger& mFlinger;
+
+ char* mWhere;
+ status_t mLastErr = NO_ERROR;
+ std::thread mThread;
+ std::condition_variable mConditionalVariable;
+ mutable std::mutex mTraceLock;
+
+ LayersTraceBuffer mBuffer GUARDED_BY(mTraceLock);
+ size_t mBufferSize GUARDED_BY(mTraceLock) = kDefaultBufferCapInByte;
+ bool mEnabled GUARDED_BY(mTraceLock) = false;
+ bool mWriteToFile GUARDED_BY(mTraceLock) = false;
};
} // namespace android