1 /* 2 * Copyright 2021 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/TransactionProto.h> 21 #include <utils/Errors.h> 22 #include <utils/Singleton.h> 23 #include <utils/Timers.h> 24 25 #include <memory> 26 #include <mutex> 27 #include <thread> 28 29 #include "FrontEnd/DisplayInfo.h" 30 #include "FrontEnd/LayerCreationArgs.h" 31 #include "FrontEnd/Update.h" 32 #include "LocklessStack.h" 33 #include "RingBuffer.h" 34 #include "TransactionProtoParser.h" 35 36 using namespace android::surfaceflinger; 37 38 namespace android { 39 40 class SurfaceFlinger; 41 class TransactionTracingTest; 42 43 /* 44 * Records all committed transactions into a ring bufffer. 45 * 46 * Transactions come in via the binder thread. They are serialized to proto 47 * and stored in a map using the transaction id as key. Main thread will 48 * pass the list of transaction ids that are committed every vsync and notify 49 * the tracing thread. The tracing thread will then wake up and add the 50 * committed transactions to the ring buffer. 51 * 52 * When generating SF dump state, we will flush the buffer to a file which 53 * will then be included in the bugreport. 54 * 55 */ 56 class TransactionTracing { 57 public: 58 TransactionTracing(); 59 ~TransactionTracing(); 60 61 void addQueuedTransaction(const TransactionState&); 62 void addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime, frontend::Update& update, 63 const frontend::DisplayInfos&, bool displayInfoChanged); 64 status_t writeToFile(const std::string& filename = FILE_PATH); 65 void setBufferSize(size_t bufferSizeInBytes); 66 void onLayerRemoved(int layerId); 67 void dump(std::string&) const; 68 // Wait until all the committed transactions for the specified vsync id are added to the buffer. 69 void flush() EXCLUDES(mMainThreadLock); 70 static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024; 71 static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024; 72 // version 1 - switching to support new frontend 73 static constexpr auto TRACING_VERSION = 1; 74 75 private: 76 friend class TransactionTracingTest; 77 friend class SurfaceFlinger; 78 79 static constexpr auto DIR_NAME = "/data/misc/wmtrace/"; 80 static constexpr auto FILE_NAME = "transactions_trace.winscope"; 81 static constexpr auto FILE_PATH = "/data/misc/wmtrace/transactions_trace.winscope"; 82 83 mutable std::mutex mTraceLock; 84 RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer 85 GUARDED_BY(mTraceLock); 86 size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; 87 std::unordered_map<uint64_t, proto::TransactionState> mQueuedTransactions 88 GUARDED_BY(mTraceLock); 89 LocklessStack<proto::TransactionState> mTransactionQueue; 90 nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock); 91 std::unordered_map<int, proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock); 92 std::map<uint32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock); 93 frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock); 94 95 std::set<uint32_t /* layerId */> mRemovedLayerHandlesAtStart GUARDED_BY(mTraceLock); 96 TransactionProtoParser mProtoParser; 97 98 // We do not want main thread to block so main thread will try to acquire mMainThreadLock, 99 // otherwise will push data to temporary container. 100 std::mutex mMainThreadLock; 101 std::thread mThread GUARDED_BY(mMainThreadLock); 102 bool mDone GUARDED_BY(mMainThreadLock) = false; 103 std::condition_variable mTransactionsAvailableCv; 104 std::condition_variable mTransactionsAddedToBufferCv; 105 struct CommittedUpdates { 106 std::vector<uint64_t> transactionIds; 107 std::vector<LayerCreationArgs> createdLayers; 108 std::vector<uint32_t> destroyedLayerHandles; 109 bool displayInfoChanged; 110 frontend::DisplayInfos displayInfos; 111 int64_t vsyncId; 112 int64_t timestamp; 113 }; 114 std::vector<CommittedUpdates> mUpdates GUARDED_BY(mMainThreadLock); 115 std::vector<CommittedUpdates> mPendingUpdates; // only accessed by main thread 116 117 std::vector<uint32_t /* layerId */> mDestroyedLayers GUARDED_BY(mMainThreadLock); 118 std::vector<uint32_t /* layerId */> mPendingDestroyedLayers; // only accessed by main thread 119 int64_t mLastUpdatedVsyncId = -1; 120 121 proto::TransactionTraceFile createTraceFileProto() const; 122 void loop(); 123 void addEntry(const std::vector<CommittedUpdates>& committedTransactions, 124 const std::vector<uint32_t>& removedLayers) EXCLUDES(mTraceLock); 125 int32_t getLayerIdLocked(const sp<IBinder>& layerHandle) REQUIRES(mTraceLock); 126 void tryPushToTracingThread() EXCLUDES(mMainThreadLock); 127 void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock); 128 void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock); 129 // TEST 130 // Return buffer contents as trace file proto 131 proto::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); 132 }; 133 134 class TransactionTraceWriter : public Singleton<TransactionTraceWriter> { 135 friend class Singleton<TransactionTracing>; 136 std::function<void(const std::string& prefix, bool overwrite)> mWriterFunction = 137 [](const std::string&, bool) {}; 138 139 public: setWriterFunction(std::function<void (const std::string & prefix,bool overwrite)> function)140 void setWriterFunction( 141 std::function<void(const std::string& prefix, bool overwrite)> function) { 142 mWriterFunction = std::move(function); 143 } invoke(const std::string & prefix,bool overwrite)144 void invoke(const std::string& prefix, bool overwrite) { mWriterFunction(prefix, overwrite); } 145 }; 146 147 } // namespace android 148