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 static LayersTraceFileProto createLayersTraceFileProto(); 77 78 private: 79 class Runner; 80 static constexpr auto DEFAULT_BUFFER_SIZE = 5_MB; 81 static constexpr auto DEFAULT_FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope"; 82 83 SurfaceFlinger& mFlinger; 84 mutable std::mutex mTraceLock; 85 bool mEnabled GUARDED_BY(mTraceLock) = false; 86 std::unique_ptr<Runner> runner GUARDED_BY(mTraceLock); 87 88 struct Config { 89 uint32_t flags = TRACE_CRITICAL | TRACE_INPUT | TRACE_SYNC; 90 size_t bufferSize = DEFAULT_BUFFER_SIZE; 91 } mConfig; 92 93 /* 94 * ring buffer. 95 */ 96 class LayersTraceBuffer { 97 public: size()98 size_t size() const { return mSizeInBytes; } used()99 size_t used() const { return mUsedInBytes; } frameCount()100 size_t frameCount() const { return mStorage.size(); } 101 setSize(size_t newSize)102 void setSize(size_t newSize) { mSizeInBytes = newSize; } 103 void reset(size_t newSize); 104 void emplace(LayersTraceProto&& proto); 105 void flush(LayersTraceFileProto* fileProto); 106 107 private: 108 size_t mUsedInBytes = 0U; 109 size_t mSizeInBytes = DEFAULT_BUFFER_SIZE; 110 std::queue<LayersTraceProto> mStorage; 111 }; 112 113 /* 114 * Implements a synchronous way of adding trace entries. This must be called 115 * from the drawing thread. 116 */ 117 class Runner { 118 public: 119 Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config); 120 virtual ~Runner() = default; 121 virtual status_t stop(); 122 virtual status_t writeToFile(); 123 virtual void notify(const char* where); 124 /* Cannot be called with a synchronous runner. */ notifyLocked(const char *)125 virtual void notifyLocked(const char* /* where */) {} 126 void dump(std::string& result) const; 127 128 protected: flagIsSet(uint32_t flags)129 bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; } 130 SurfaceFlinger& mFlinger; 131 SurfaceTracing::Config mConfig; 132 SurfaceTracing::LayersTraceBuffer mBuffer; 133 uint32_t mMissedTraceEntries = 0; 134 LayersTraceProto traceLayers(const char* where); 135 }; 136 137 /* 138 * Implements asynchronous way to add trace entries called from a separate thread while holding 139 * the SurfaceFlinger tracing lock. Trace entries may be missed if the tracing thread is not 140 * scheduled in time. 141 */ 142 class AsyncRunner : public Runner { 143 public: 144 AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config, std::mutex& sfLock); 145 virtual ~AsyncRunner() = default; 146 status_t stop() override; 147 status_t writeToFile() override; 148 void notify(const char* where) override; 149 void notifyLocked(const char* where); 150 151 private: 152 std::mutex& mSfLock; 153 std::condition_variable mCanStartTrace; 154 std::thread mThread; 155 const char* mWhere = ""; 156 bool mWriteToFile = false; 157 bool mEnabled = false; 158 bool mAddEntry = false; 159 void loop(); 160 bool traceWhenNotified(LayersTraceProto* outProto); 161 }; 162 }; 163 164 } // namespace android 165