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 <layerproto/LayerProtoHeader.h>
20 #include <utils/Errors.h>
21 #include <utils/StrongPointer.h>
22 
23 #include <android-base/thread_annotations.h>
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 
36 constexpr auto operator""_MB(unsigned long long const num) {
37     return num * 1024 * 1024;
38 }
39 /*
40  * SurfaceTracing records layer states during surface flinging.
41  */
42 class SurfaceTracing {
43 public:
44     explicit SurfaceTracing(SurfaceFlinger& flinger);
45     void enable();
46     bool disable();
47     status_t writeToFile();
48     bool isEnabled() const;
49     void notify(long compositionTime, const char* where);
50 
51     void setBufferSize(size_t bufferSizeInByte);
52     void writeToFileAsync();
53     void dump(std::string& result) const;
54 
55     enum : uint32_t {
56         TRACE_CRITICAL = 1 << 0,
57         TRACE_INPUT = 1 << 1,
58         TRACE_EXTRA = 1 << 2,
59         TRACE_ALL = 0xffffffff
60     };
61     void setTraceFlags(uint32_t flags);
62 
63 private:
64     static constexpr auto kDefaultBufferCapInByte = 100_MB;
65     static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb";
66 
67     class LayersTraceBuffer { // ring buffer
68     public:
size()69         size_t size() const { return mSizeInBytes; }
used()70         size_t used() const { return mUsedInBytes; }
frameCount()71         size_t frameCount() const { return mStorage.size(); }
72 
setSize(size_t newSize)73         void setSize(size_t newSize) { mSizeInBytes = newSize; }
74         void reset(size_t newSize);
75         void emplace(LayersTraceProto&& proto);
76         void flush(LayersTraceFileProto* fileProto);
77 
78     private:
79         size_t mUsedInBytes = 0U;
80         size_t mSizeInBytes = 0U;
81         std::queue<LayersTraceProto> mStorage;
82     };
83 
84     long mCompositionTime;
85 
86     void mainLoop();
87     void addFirstEntry();
88     LayersTraceProto traceWhenNotified();
89     LayersTraceProto traceLayersLocked(const char* where) REQUIRES(mSfLock);
90 
91     // Returns true if trace is enabled.
92     bool addTraceToBuffer(LayersTraceProto& entry);
93     void writeProtoFileLocked() REQUIRES(mTraceLock);
94 
95     const SurfaceFlinger& mFlinger;
96     status_t mLastErr = NO_ERROR;
97     std::thread mThread;
98     std::condition_variable mCanStartTrace;
99 
100     std::mutex& mSfLock;
101     uint32_t mTraceFlags GUARDED_BY(mSfLock) = TRACE_ALL;
102     const char* mWhere GUARDED_BY(mSfLock) = "";
103 
104     mutable std::mutex mTraceLock;
105     LayersTraceBuffer mBuffer GUARDED_BY(mTraceLock);
106     size_t mBufferSize GUARDED_BY(mTraceLock) = kDefaultBufferCapInByte;
107     bool mEnabled GUARDED_BY(mTraceLock) = false;
108     bool mWriteToFile GUARDED_BY(mTraceLock) = false;
109 };
110 
111 } // namespace android
112