blob: d84ce69e56fddda1c5534a7fb06cb7aabd938b9f [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)
Dominik Laskowski542c9dc2020-04-10 12:42:02 -070036 : mFlinger(flinger), mSfLock(flinger.mTracingLock) {}
Nataniel Borges2b796da2019-02-15 13:32:18 -080037
Vishnu Nair9245d3b2019-03-22 13:38:56 -070038void SurfaceTracing::mainLoop() {
Vishnu Nair73454c32020-04-03 18:56:19 -070039 bool enabled = addFirstEntry();
Vishnu Nair9245d3b2019-03-22 13:38:56 -070040 while (enabled) {
41 LayersTraceProto entry = traceWhenNotified();
42 enabled = addTraceToBuffer(entry);
43 }
Nataniel Borges2b796da2019-02-15 13:32:18 -080044}
45
Vishnu Nair73454c32020-04-03 18:56:19 -070046bool SurfaceTracing::addFirstEntry() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070047 LayersTraceProto entry;
48 {
49 std::scoped_lock lock(mSfLock);
Dominik Laskowski542c9dc2020-04-10 12:42:02 -070050 entry = traceLayersLocked("tracing.enable");
Vishnu Nair9245d3b2019-03-22 13:38:56 -070051 }
Vishnu Nair73454c32020-04-03 18:56:19 -070052 return addTraceToBuffer(entry);
Vishnu Nair9245d3b2019-03-22 13:38:56 -070053}
54
55LayersTraceProto SurfaceTracing::traceWhenNotified() {
56 std::unique_lock<std::mutex> lock(mSfLock);
57 mCanStartTrace.wait(lock);
58 android::base::ScopedLockAssertion assumeLock(mSfLock);
Dominik Laskowski542c9dc2020-04-10 12:42:02 -070059 LayersTraceProto entry = traceLayersLocked(mWhere);
Vishnu Nair60db8c02020-04-02 11:55:16 -070060 mTracingInProgress = false;
61 mMissedTraceEntries = 0;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070062 lock.unlock();
63 return entry;
64}
65
66bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) {
67 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080068 mBuffer.emplace(std::move(entry));
Vishnu Nair9245d3b2019-03-22 13:38:56 -070069 if (mWriteToFile) {
70 writeProtoFileLocked();
71 mWriteToFile = false;
72 }
73 return mEnabled;
Nataniel Borges2b796da2019-02-15 13:32:18 -080074}
75
76void SurfaceTracing::notify(const char* where) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070077 std::scoped_lock lock(mSfLock);
Vishnu Nair60db8c02020-04-02 11:55:16 -070078 notifyLocked(where);
79}
80
81void SurfaceTracing::notifyLocked(const char* where) {
Vishnu Nairb0159482019-03-18 12:48:46 -070082 mWhere = where;
Vishnu Nair60db8c02020-04-02 11:55:16 -070083 if (mTracingInProgress) {
84 mMissedTraceEntries++;
85 }
86 mTracingInProgress = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070087 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080088}
89
90void SurfaceTracing::writeToFileAsync() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070091 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080092 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070093 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080094}
95
Yichi Chen9c696ed2018-10-01 22:32:30 +080096void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
97 // use the swap trick to make sure memory is released
98 std::queue<LayersTraceProto>().swap(mStorage);
99 mSizeInBytes = newSize;
100 mUsedInBytes = 0U;
101}
102
103void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
104 auto protoSize = proto.ByteSize();
105 while (mUsedInBytes + protoSize > mSizeInBytes) {
106 if (mStorage.empty()) {
107 return;
108 }
109 mUsedInBytes -= mStorage.front().ByteSize();
110 mStorage.pop();
111 }
112 mUsedInBytes += protoSize;
113 mStorage.emplace();
114 mStorage.back().Swap(&proto);
115}
116
117void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
118 fileProto->mutable_entry()->Reserve(mStorage.size());
119
120 while (!mStorage.empty()) {
121 auto entry = fileProto->add_entry();
122 entry->Swap(&mStorage.front());
123 mStorage.pop();
124 }
125}
126
Dominik Laskowski542c9dc2020-04-10 12:42:02 -0700127bool SurfaceTracing::enable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700128 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700129
Adrian Roos1e1a1282017-11-01 19:05:31 +0100130 if (mEnabled) {
Dominik Laskowski542c9dc2020-04-10 12:42:02 -0700131 return false;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100132 }
Dominik Laskowski542c9dc2020-04-10 12:42:02 -0700133
Nataniel Borges2b796da2019-02-15 13:32:18 -0800134 mBuffer.reset(mBufferSize);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100135 mEnabled = true;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800136 mThread = std::thread(&SurfaceTracing::mainLoop, this);
Dominik Laskowski542c9dc2020-04-10 12:42:02 -0700137 return true;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100138}
139
Nataniel Borges2b796da2019-02-15 13:32:18 -0800140status_t SurfaceTracing::writeToFile() {
Alec Mouri50aeef62020-03-25 18:52:29 -0700141 std::thread thread;
142 {
143 std::scoped_lock lock(mTraceLock);
144 thread = std::move(mThread);
145 }
146 thread.join();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800147 return mLastErr;
148}
149
150bool SurfaceTracing::disable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700151 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700152
Adrian Roos1e1a1282017-11-01 19:05:31 +0100153 if (!mEnabled) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800154 return false;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100155 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800156
Adrian Roos1e1a1282017-11-01 19:05:31 +0100157 mEnabled = false;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800158 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700159 mCanStartTrace.notify_all();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800160 return true;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100161}
162
Yichi Chenadc69612018-09-15 14:51:18 +0800163bool SurfaceTracing::isEnabled() const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700164 std::scoped_lock lock(mTraceLock);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100165 return mEnabled;
166}
167
Nataniel Borges2b796da2019-02-15 13:32:18 -0800168void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700169 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800170 mBufferSize = bufferSizeInByte;
171 mBuffer.setSize(bufferSizeInByte);
172}
173
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700174void SurfaceTracing::setTraceFlags(uint32_t flags) {
175 std::scoped_lock lock(mSfLock);
176 mTraceFlags = flags;
177}
178
Dominik Laskowski542c9dc2020-04-10 12:42:02 -0700179LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800180 ATRACE_CALL();
Yichi Chenadc69612018-09-15 14:51:18 +0800181
Yichi Chen9c696ed2018-10-01 22:32:30 +0800182 LayersTraceProto entry;
183 entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
184 entry.set_where(where);
Dominik Laskowski542c9dc2020-04-10 12:42:02 -0700185 LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
Vishnu Nair60db8c02020-04-02 11:55:16 -0700186
187 if (flagIsSetLocked(SurfaceTracing::TRACE_EXTRA)) {
188 mFlinger.dumpOffscreenLayersProto(layers);
189 }
Yichi Chen9c696ed2018-10-01 22:32:30 +0800190 entry.mutable_layers()->Swap(&layers);
191
Alec Mouri6b9e9912020-01-21 10:50:24 -0800192 if (mTraceFlags & SurfaceTracing::TRACE_HWC) {
193 std::string hwcDump;
194 mFlinger.dumpHwc(hwcDump);
195 entry.set_hwc_blob(hwcDump);
196 }
Vishnu Nair60db8c02020-04-02 11:55:16 -0700197 if (!flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION)) {
198 entry.set_excludes_composition_state(true);
199 }
200 entry.set_missed_entries(mMissedTraceEntries);
Alec Mouri6b9e9912020-01-21 10:50:24 -0800201
Nataniel Borges2b796da2019-02-15 13:32:18 -0800202 return entry;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100203}
204
Nataniel Borges2b796da2019-02-15 13:32:18 -0800205void SurfaceTracing::writeProtoFileLocked() {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100206 ATRACE_CALL();
207
Yichi Chen9c696ed2018-10-01 22:32:30 +0800208 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100209 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800210
211 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
212 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
213 mBuffer.flush(&fileProto);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800214 mBuffer.reset(mBufferSize);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800215
216 if (!fileProto.SerializeToString(&output)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800217 ALOGE("Could not save the proto file! Permission denied");
218 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100219 }
chaviwd1759e02020-01-23 11:28:09 -0800220
221 // -rw-r--r--
222 const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
223 if (!android::base::WriteStringToFile(output, kDefaultFileName, mode, getuid(), getgid(),
224 true)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800225 ALOGE("Could not save the proto file! There are missing fields");
226 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100227 }
228
Nataniel Borges2b796da2019-02-15 13:32:18 -0800229 mLastErr = NO_ERROR;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100230}
231
Yiwei Zhang5434a782018-12-05 18:06:32 -0800232void SurfaceTracing::dump(std::string& result) const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700233 std::scoped_lock lock(mTraceLock);
Yiwei Zhang5434a782018-12-05 18:06:32 -0800234 base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
235 base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
236 mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
237 float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800238}
239
Adrian Roos1e1a1282017-11-01 19:05:31 +0100240} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800241
242// TODO(b/129481165): remove the #pragma below and fix conversion issues
243#pragma clang diagnostic pop // ignored "-Wconversion"