• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Timers.h>
23 
24 #include <memory>
25 #include <mutex>
26 #include <thread>
27 
28 #include "RingBuffer.h"
29 #include "LocklessStack.h"
30 #include "TransactionProtoParser.h"
31 
32 using namespace android::surfaceflinger;
33 
34 namespace android {
35 
36 class SurfaceFlinger;
37 class TransactionTracingTest;
38 
39 /*
40  * Records all committed transactions into a ring bufffer.
41  *
42  * Transactions come in via the binder thread. They are serialized to proto
43  * and stored in a map using the transaction id as key. Main thread will
44  * pass the list of transaction ids that are committed every vsync and notify
45  * the tracing thread. The tracing thread will then wake up and add the
46  * committed transactions to the ring buffer.
47  *
48  * When generating SF dump state, we will flush the buffer to a file which
49  * will then be included in the bugreport.
50  *
51  */
52 class TransactionTracing {
53 public:
54     TransactionTracing();
55     ~TransactionTracing();
56 
57     void addQueuedTransaction(const TransactionState&);
58     void addCommittedTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId);
59     status_t writeToFile(std::string filename = FILE_NAME);
60     void setBufferSize(size_t bufferSizeInBytes);
61     void onLayerAdded(BBinder* layerHandle, int layerId, const std::string& name, uint32_t flags,
62                       int parentId);
63     void onMirrorLayerAdded(BBinder* layerHandle, int layerId, const std::string& name,
64                             int mirrorFromId);
65     void onLayerRemoved(int layerId);
66     void onHandleRemoved(BBinder* layerHandle);
67     void dump(std::string&) const;
68     static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
69     static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
70 
71 private:
72     friend class TransactionTracingTest;
73 
74     static constexpr auto FILE_NAME = "/data/misc/wmtrace/transactions_trace.winscope";
75 
76     mutable std::mutex mTraceLock;
77     RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer
78             GUARDED_BY(mTraceLock);
79     size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE;
80     std::unordered_map<uint64_t, proto::TransactionState> mQueuedTransactions
81             GUARDED_BY(mTraceLock);
82     LocklessStack<proto::TransactionState> mTransactionQueue;
83     nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
84     std::vector<proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
85     std::unordered_map<BBinder* /* layerHandle */, int32_t /* layerId */> mLayerHandles
86             GUARDED_BY(mTraceLock);
87     std::vector<int32_t /* layerId */> mRemovedLayerHandles GUARDED_BY(mTraceLock);
88     std::map<int32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
89     TransactionProtoParser mProtoParser GUARDED_BY(mTraceLock);
90     // Parses the transaction to proto without holding any tracing locks so we can generate proto
91     // in the binder thread without any contention.
92     TransactionProtoParser mLockfreeProtoParser;
93 
94     // We do not want main thread to block so main thread will try to acquire mMainThreadLock,
95     // otherwise will push data to temporary container.
96     std::mutex mMainThreadLock;
97     std::thread mThread GUARDED_BY(mMainThreadLock);
98     bool mDone GUARDED_BY(mMainThreadLock) = false;
99     std::condition_variable mTransactionsAvailableCv;
100     std::condition_variable mTransactionsAddedToBufferCv;
101     struct CommittedTransactions {
102         std::vector<uint64_t> transactionIds;
103         int64_t vsyncId;
104         int64_t timestamp;
105     };
106     std::vector<CommittedTransactions> mCommittedTransactions GUARDED_BY(mMainThreadLock);
107     std::vector<CommittedTransactions> mPendingTransactions; // only accessed by main thread
108 
109     std::vector<int32_t /* layerId */> mRemovedLayers GUARDED_BY(mMainThreadLock);
110     std::vector<int32_t /* layerId */> mPendingRemovedLayers; // only accessed by main thread
111 
112     proto::TransactionTraceFile createTraceFileProto() const;
113     void loop();
114     void addEntry(const std::vector<CommittedTransactions>& committedTransactions,
115                   const std::vector<int32_t>& removedLayers) EXCLUDES(mTraceLock);
116     int32_t getLayerIdLocked(const sp<IBinder>& layerHandle) REQUIRES(mTraceLock);
117     void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
118     void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock);
119     void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock);
120 
121     // TEST
122     // Wait until all the committed transactions for the specified vsync id are added to the buffer.
123     void flush(int64_t vsyncId) EXCLUDES(mMainThreadLock);
124     // Return buffer contents as trace file proto
125     proto::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock);
126 };
127 
128 } // namespace android
129