1 /* 2 * Copyright 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <android-base/thread_annotations.h> 20 #include <layerproto/LayerProtoHeader.h> 21 #include <utils/Errors.h> 22 #include <utils/StrongPointer.h> 23 24 #include <condition_variable> 25 #include <memory> 26 #include <mutex> 27 #include <queue> 28 #include <thread> 29 30 using namespace android::surfaceflinger; 31 32 namespace android { 33 34 class SurfaceFlinger; 35 constexpr auto operator""_MB(unsigned long long const num) { 36 return num * 1024 * 1024; 37 } 38 /* 39 * SurfaceTracing records layer states during surface flinging. Manages tracing state and 40 * configuration. 41 */ 42 class SurfaceTracing { 43 public: 44 SurfaceTracing(SurfaceFlinger& flinger); 45 bool enable(); 46 bool disable(); 47 status_t writeToFile(); 48 bool isEnabled() const; 49 /* 50 * Adds a trace entry, must be called from the drawing thread or while holding the 51 * SurfaceFlinger tracing lock. 52 */ 53 void notify(const char* where); 54 /* 55 * Adds a trace entry, called while holding the SurfaceFlinger tracing lock. 56 */ 57 void notifyLocked(const char* where) /* REQUIRES(mSfLock) */; 58 setBufferSize(size_t bufferSizeInBytes)59 void setBufferSize(size_t bufferSizeInBytes) { mConfig.bufferSize = bufferSizeInBytes; } 60 void dump(std::string& result) const; 61 62 enum : uint32_t { 63 TRACE_CRITICAL = 1 << 0, 64 TRACE_INPUT = 1 << 1, 65 TRACE_COMPOSITION = 1 << 2, 66 TRACE_EXTRA = 1 << 3, 67 TRACE_HWC = 1 << 4, 68 // Add non-geometry composition changes to the trace. 69 TRACE_BUFFERS = 1 << 5, 70 // Add entries from the drawing thread post composition. 71 TRACE_SYNC = 1 << 6, 72 TRACE_ALL = TRACE_CRITICAL | TRACE_INPUT | TRACE_COMPOSITION | TRACE_EXTRA, 73 }; setTraceFlags(uint32_t flags)74 void setTraceFlags(uint32_t flags) { mConfig.flags = flags; } flagIsSet(uint32_t flags)75 bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; } 76 77 private: 78 class Runner; 79 static constexpr auto DEFAULT_BUFFER_SIZE = 5_MB; 80 static constexpr auto DEFAULT_FILE_NAME = "/data/misc/wmtrace/layers_trace.pb"; 81 82 SurfaceFlinger& mFlinger; 83 mutable std::mutex mTraceLock; 84 bool mEnabled GUARDED_BY(mTraceLock) = false; 85 std::unique_ptr<Runner> runner GUARDED_BY(mTraceLock); 86 87 struct Config { 88 uint32_t flags = TRACE_CRITICAL | TRACE_INPUT | TRACE_SYNC; 89 size_t bufferSize = DEFAULT_BUFFER_SIZE; 90 } mConfig; 91 92 /* 93 * ring buffer. 94 */ 95 class LayersTraceBuffer { 96 public: size()97 size_t size() const { return mSizeInBytes; } used()98 size_t used() const { return mUsedInBytes; } frameCount()99 size_t frameCount() const { return mStorage.size(); } 100 setSize(size_t newSize)101 void setSize(size_t newSize) { mSizeInBytes = newSize; } 102 void reset(size_t newSize); 103 void emplace(LayersTraceProto&& proto); 104 void flush(LayersTraceFileProto* fileProto); 105 106 private: 107 size_t mUsedInBytes = 0U; 108 size_t mSizeInBytes = DEFAULT_BUFFER_SIZE; 109 std::queue<LayersTraceProto> mStorage; 110 }; 111 112 /* 113 * Implements a synchronous way of adding trace entries. This must be called 114 * from the drawing thread. 115 */ 116 class Runner { 117 public: 118 Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config); 119 virtual ~Runner() = default; 120 virtual status_t stop(); 121 virtual status_t writeToFile(); 122 virtual void notify(const char* where); 123 /* Cannot be called with a synchronous runner. */ notifyLocked(const char *)124 virtual void notifyLocked(const char* /* where */) {} 125 void dump(std::string& result) const; 126 127 protected: flagIsSet(uint32_t flags)128 bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; } 129 SurfaceFlinger& mFlinger; 130 SurfaceTracing::Config mConfig; 131 SurfaceTracing::LayersTraceBuffer mBuffer; 132 uint32_t mMissedTraceEntries = 0; 133 LayersTraceProto traceLayers(const char* where); 134 }; 135 136 /* 137 * Implements asynchronous way to add trace entries called from a separate thread while holding 138 * the SurfaceFlinger tracing lock. Trace entries may be missed if the tracing thread is not 139 * scheduled in time. 140 */ 141 class AsyncRunner : public Runner { 142 public: 143 AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config, std::mutex& sfLock); 144 virtual ~AsyncRunner() = default; 145 status_t stop() override; 146 status_t writeToFile() override; 147 void notify(const char* where) override; 148 void notifyLocked(const char* where); 149 150 private: 151 std::mutex& mSfLock; 152 std::condition_variable mCanStartTrace; 153 std::thread mThread; 154 const char* mWhere = ""; 155 bool mWriteToFile = false; 156 bool mEnabled = false; 157 bool mAddEntry = false; 158 void loop(); 159 bool traceWhenNotified(LayersTraceProto* outProto); 160 }; 161 }; 162 163 } // namespace android 164