blob: 0b1251eac6ad5b3b439a1ab3b760da236149688b [file] [log] [blame]
Adrian Roos1e1a1282017-11-01 19:05:31 +01001/*
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 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080016
17// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
Adrian Roos1e1a1282017-11-01 19:05:31 +010020#undef LOG_TAG
21#define LOG_TAG "SurfaceTracing"
22#define ATRACE_TAG ATRACE_TAG_GRAPHICS
23
24#include "SurfaceTracing.h"
Nataniel Borges2b796da2019-02-15 13:32:18 -080025#include <SurfaceFlinger.h>
Adrian Roos1e1a1282017-11-01 19:05:31 +010026
27#include <android-base/file.h>
Yiwei Zhang5434a782018-12-05 18:06:32 -080028#include <android-base/stringprintf.h>
Adrian Roos1e1a1282017-11-01 19:05:31 +010029#include <log/log.h>
30#include <utils/SystemClock.h>
31#include <utils/Trace.h>
32
33namespace android {
34
Vishnu Nair9245d3b2019-03-22 13:38:56 -070035SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger)
36 : mFlinger(flinger), mSfLock(flinger.mDrawingStateLock) {}
Nataniel Borges2b796da2019-02-15 13:32:18 -080037
Vishnu Nair9245d3b2019-03-22 13:38:56 -070038void SurfaceTracing::mainLoop() {
39 addFirstEntry();
40 bool enabled = true;
41 while (enabled) {
42 LayersTraceProto entry = traceWhenNotified();
43 enabled = addTraceToBuffer(entry);
44 }
Nataniel Borges2b796da2019-02-15 13:32:18 -080045}
46
Vishnu Nair9245d3b2019-03-22 13:38:56 -070047void SurfaceTracing::addFirstEntry() {
Alec Mouri5793c7d2020-03-10 19:55:50 -070048 const auto displayDevice = mFlinger.getDefaultDisplayDevice();
Vishnu Nair9245d3b2019-03-22 13:38:56 -070049 LayersTraceProto entry;
50 {
51 std::scoped_lock lock(mSfLock);
Alec Mouri5793c7d2020-03-10 19:55:50 -070052 entry = traceLayersLocked("tracing.enable", displayDevice);
Vishnu Nair9245d3b2019-03-22 13:38:56 -070053 }
54 addTraceToBuffer(entry);
55}
56
57LayersTraceProto SurfaceTracing::traceWhenNotified() {
Alec Mouri5793c7d2020-03-10 19:55:50 -070058 const auto displayDevice = mFlinger.getDefaultDisplayDevice();
Vishnu Nair9245d3b2019-03-22 13:38:56 -070059 std::unique_lock<std::mutex> lock(mSfLock);
60 mCanStartTrace.wait(lock);
61 android::base::ScopedLockAssertion assumeLock(mSfLock);
Alec Mouri5793c7d2020-03-10 19:55:50 -070062 LayersTraceProto entry = traceLayersLocked(mWhere, displayDevice);
Vishnu Nair60db8c02020-04-02 11:55:16 -070063 mTracingInProgress = false;
64 mMissedTraceEntries = 0;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070065 lock.unlock();
66 return entry;
67}
68
69bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) {
70 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080071 mBuffer.emplace(std::move(entry));
Vishnu Nair9245d3b2019-03-22 13:38:56 -070072 if (mWriteToFile) {
73 writeProtoFileLocked();
74 mWriteToFile = false;
75 }
76 return mEnabled;
Nataniel Borges2b796da2019-02-15 13:32:18 -080077}
78
79void SurfaceTracing::notify(const char* where) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070080 std::scoped_lock lock(mSfLock);
Vishnu Nair60db8c02020-04-02 11:55:16 -070081 notifyLocked(where);
82}
83
84void SurfaceTracing::notifyLocked(const char* where) {
Vishnu Nairb0159482019-03-18 12:48:46 -070085 mWhere = where;
Vishnu Nair60db8c02020-04-02 11:55:16 -070086 if (mTracingInProgress) {
87 mMissedTraceEntries++;
88 }
89 mTracingInProgress = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070090 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080091}
92
93void SurfaceTracing::writeToFileAsync() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070094 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080095 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070096 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080097}
98
Yichi Chen9c696ed2018-10-01 22:32:30 +080099void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
100 // use the swap trick to make sure memory is released
101 std::queue<LayersTraceProto>().swap(mStorage);
102 mSizeInBytes = newSize;
103 mUsedInBytes = 0U;
104}
105
106void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
107 auto protoSize = proto.ByteSize();
108 while (mUsedInBytes + protoSize > mSizeInBytes) {
109 if (mStorage.empty()) {
110 return;
111 }
112 mUsedInBytes -= mStorage.front().ByteSize();
113 mStorage.pop();
114 }
115 mUsedInBytes += protoSize;
116 mStorage.emplace();
117 mStorage.back().Swap(&proto);
118}
119
120void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
121 fileProto->mutable_entry()->Reserve(mStorage.size());
122
123 while (!mStorage.empty()) {
124 auto entry = fileProto->add_entry();
125 entry->Swap(&mStorage.front());
126 mStorage.pop();
127 }
128}
129
Nataniel Borges2b796da2019-02-15 13:32:18 -0800130void SurfaceTracing::enable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700131 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700132
Adrian Roos1e1a1282017-11-01 19:05:31 +0100133 if (mEnabled) {
134 return;
135 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800136 mBuffer.reset(mBufferSize);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100137 mEnabled = true;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800138 mThread = std::thread(&SurfaceTracing::mainLoop, this);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100139}
140
Nataniel Borges2b796da2019-02-15 13:32:18 -0800141status_t SurfaceTracing::writeToFile() {
Alec Mouri50aeef62020-03-25 18:52:29 -0700142 std::thread thread;
143 {
144 std::scoped_lock lock(mTraceLock);
145 thread = std::move(mThread);
146 }
147 thread.join();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800148 return mLastErr;
149}
150
151bool SurfaceTracing::disable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700152 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700153
Adrian Roos1e1a1282017-11-01 19:05:31 +0100154 if (!mEnabled) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800155 return false;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100156 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800157
Adrian Roos1e1a1282017-11-01 19:05:31 +0100158 mEnabled = false;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800159 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700160 mCanStartTrace.notify_all();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800161 return true;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100162}
163
Yichi Chenadc69612018-09-15 14:51:18 +0800164bool SurfaceTracing::isEnabled() const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700165 std::scoped_lock lock(mTraceLock);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100166 return mEnabled;
167}
168
Nataniel Borges2b796da2019-02-15 13:32:18 -0800169void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700170 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800171 mBufferSize = bufferSizeInByte;
172 mBuffer.setSize(bufferSizeInByte);
173}
174
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700175void SurfaceTracing::setTraceFlags(uint32_t flags) {
176 std::scoped_lock lock(mSfLock);
177 mTraceFlags = flags;
178}
179
Alec Mouri5793c7d2020-03-10 19:55:50 -0700180LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where,
181 const sp<const DisplayDevice>& displayDevice) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800182 ATRACE_CALL();
Yichi Chenadc69612018-09-15 14:51:18 +0800183
Yichi Chen9c696ed2018-10-01 22:32:30 +0800184 LayersTraceProto entry;
185 entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
186 entry.set_where(where);
Alec Mouri5793c7d2020-03-10 19:55:50 -0700187 LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags, displayDevice));
Vishnu Nair60db8c02020-04-02 11:55:16 -0700188
189 if (flagIsSetLocked(SurfaceTracing::TRACE_EXTRA)) {
190 mFlinger.dumpOffscreenLayersProto(layers);
191 }
Yichi Chen9c696ed2018-10-01 22:32:30 +0800192 entry.mutable_layers()->Swap(&layers);
193
Alec Mouri6b9e9912020-01-21 10:50:24 -0800194 if (mTraceFlags & SurfaceTracing::TRACE_HWC) {
195 std::string hwcDump;
196 mFlinger.dumpHwc(hwcDump);
197 entry.set_hwc_blob(hwcDump);
198 }
Vishnu Nair60db8c02020-04-02 11:55:16 -0700199 if (!flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION)) {
200 entry.set_excludes_composition_state(true);
201 }
202 entry.set_missed_entries(mMissedTraceEntries);
Alec Mouri6b9e9912020-01-21 10:50:24 -0800203
Nataniel Borges2b796da2019-02-15 13:32:18 -0800204 return entry;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100205}
206
Nataniel Borges2b796da2019-02-15 13:32:18 -0800207void SurfaceTracing::writeProtoFileLocked() {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100208 ATRACE_CALL();
209
Yichi Chen9c696ed2018-10-01 22:32:30 +0800210 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100211 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800212
213 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
214 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
215 mBuffer.flush(&fileProto);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800216 mBuffer.reset(mBufferSize);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800217
218 if (!fileProto.SerializeToString(&output)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800219 ALOGE("Could not save the proto file! Permission denied");
220 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100221 }
chaviwd1759e02020-01-23 11:28:09 -0800222
223 // -rw-r--r--
224 const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
225 if (!android::base::WriteStringToFile(output, kDefaultFileName, mode, getuid(), getgid(),
226 true)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800227 ALOGE("Could not save the proto file! There are missing fields");
228 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100229 }
230
Nataniel Borges2b796da2019-02-15 13:32:18 -0800231 mLastErr = NO_ERROR;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100232}
233
Yiwei Zhang5434a782018-12-05 18:06:32 -0800234void SurfaceTracing::dump(std::string& result) const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700235 std::scoped_lock lock(mTraceLock);
Yiwei Zhang5434a782018-12-05 18:06:32 -0800236 base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
237 base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
238 mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
239 float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800240}
241
Adrian Roos1e1a1282017-11-01 19:05:31 +0100242} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800243
244// TODO(b/129481165): remove the #pragma below and fix conversion issues
245#pragma clang diagnostic pop // ignored "-Wconversion"