• 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/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