• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
77 private:
78     class Runner;
79     static constexpr auto DEFAULT_BUFFER_SIZE = 5_MB;
80     static constexpr auto DEFAULT_FILE_NAME = "/data/misc/wmtrace/layers_trace.pb";
81 
82     SurfaceFlinger& mFlinger;
83     mutable std::mutex mTraceLock;
84     bool mEnabled GUARDED_BY(mTraceLock) = false;
85     std::unique_ptr<Runner> runner GUARDED_BY(mTraceLock);
86 
87     struct Config {
88         uint32_t flags = TRACE_CRITICAL | TRACE_INPUT | TRACE_SYNC;
89         size_t bufferSize = DEFAULT_BUFFER_SIZE;
90     } mConfig;
91 
92     /*
93      * ring buffer.
94      */
95     class LayersTraceBuffer {
96     public:
size()97         size_t size() const { return mSizeInBytes; }
used()98         size_t used() const { return mUsedInBytes; }
frameCount()99         size_t frameCount() const { return mStorage.size(); }
100 
setSize(size_t newSize)101         void setSize(size_t newSize) { mSizeInBytes = newSize; }
102         void reset(size_t newSize);
103         void emplace(LayersTraceProto&& proto);
104         void flush(LayersTraceFileProto* fileProto);
105 
106     private:
107         size_t mUsedInBytes = 0U;
108         size_t mSizeInBytes = DEFAULT_BUFFER_SIZE;
109         std::queue<LayersTraceProto> mStorage;
110     };
111 
112     /*
113      * Implements a synchronous way of adding trace entries. This must be called
114      * from the drawing thread.
115      */
116     class Runner {
117     public:
118         Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config);
119         virtual ~Runner() = default;
120         virtual status_t stop();
121         virtual status_t writeToFile();
122         virtual void notify(const char* where);
123         /* Cannot be called with a synchronous runner. */
notifyLocked(const char *)124         virtual void notifyLocked(const char* /* where */) {}
125         void dump(std::string& result) const;
126 
127     protected:
flagIsSet(uint32_t flags)128         bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; }
129         SurfaceFlinger& mFlinger;
130         SurfaceTracing::Config mConfig;
131         SurfaceTracing::LayersTraceBuffer mBuffer;
132         uint32_t mMissedTraceEntries = 0;
133         LayersTraceProto traceLayers(const char* where);
134     };
135 
136     /*
137      * Implements asynchronous way to add trace entries called from a separate thread while holding
138      * the SurfaceFlinger tracing lock. Trace entries may be missed if the tracing thread is not
139      * scheduled in time.
140      */
141     class AsyncRunner : public Runner {
142     public:
143         AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config, std::mutex& sfLock);
144         virtual ~AsyncRunner() = default;
145         status_t stop() override;
146         status_t writeToFile() override;
147         void notify(const char* where) override;
148         void notifyLocked(const char* where);
149 
150     private:
151         std::mutex& mSfLock;
152         std::condition_variable mCanStartTrace;
153         std::thread mThread;
154         const char* mWhere = "";
155         bool mWriteToFile = false;
156         bool mEnabled = false;
157         bool mAddEntry = false;
158         void loop();
159         bool traceWhenNotified(LayersTraceProto* outProto);
160     };
161 };
162 
163 } // namespace android
164