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