blob: c4ab0668e75a22f9d17094033e923df57dab0e41 [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 */
16#undef LOG_TAG
17#define LOG_TAG "SurfaceTracing"
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20#include "SurfaceTracing.h"
Nataniel Borges2b796da2019-02-15 13:32:18 -080021#include <SurfaceFlinger.h>
Adrian Roos1e1a1282017-11-01 19:05:31 +010022
23#include <android-base/file.h>
Yiwei Zhang5434a782018-12-05 18:06:32 -080024#include <android-base/stringprintf.h>
Adrian Roos1e1a1282017-11-01 19:05:31 +010025#include <log/log.h>
26#include <utils/SystemClock.h>
27#include <utils/Trace.h>
28
29namespace android {
30
Vishnu Nair9245d3b2019-03-22 13:38:56 -070031SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger)
32 : mFlinger(flinger), mSfLock(flinger.mDrawingStateLock) {}
Nataniel Borges2b796da2019-02-15 13:32:18 -080033
Vishnu Nair9245d3b2019-03-22 13:38:56 -070034void SurfaceTracing::mainLoop() {
35 addFirstEntry();
36 bool enabled = true;
37 while (enabled) {
38 LayersTraceProto entry = traceWhenNotified();
39 enabled = addTraceToBuffer(entry);
40 }
Nataniel Borges2b796da2019-02-15 13:32:18 -080041}
42
Vishnu Nair9245d3b2019-03-22 13:38:56 -070043void SurfaceTracing::addFirstEntry() {
44 LayersTraceProto entry;
45 {
46 std::scoped_lock lock(mSfLock);
47 entry = traceLayersLocked("tracing.enable");
48 }
49 addTraceToBuffer(entry);
50}
51
52LayersTraceProto SurfaceTracing::traceWhenNotified() {
53 std::unique_lock<std::mutex> lock(mSfLock);
54 mCanStartTrace.wait(lock);
55 android::base::ScopedLockAssertion assumeLock(mSfLock);
56 LayersTraceProto entry = traceLayersLocked(mWhere);
57 lock.unlock();
58 return entry;
59}
60
61bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) {
62 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080063 mBuffer.emplace(std::move(entry));
Vishnu Nair9245d3b2019-03-22 13:38:56 -070064 if (mWriteToFile) {
65 writeProtoFileLocked();
66 mWriteToFile = false;
67 }
68 return mEnabled;
Nataniel Borges2b796da2019-02-15 13:32:18 -080069}
70
71void SurfaceTracing::notify(const char* where) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070072 std::scoped_lock lock(mSfLock);
Vishnu Nairb0159482019-03-18 12:48:46 -070073 mWhere = where;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070074 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080075}
76
77void SurfaceTracing::writeToFileAsync() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070078 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080079 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070080 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080081}
82
Yichi Chen9c696ed2018-10-01 22:32:30 +080083void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
84 // use the swap trick to make sure memory is released
85 std::queue<LayersTraceProto>().swap(mStorage);
86 mSizeInBytes = newSize;
87 mUsedInBytes = 0U;
88}
89
90void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
91 auto protoSize = proto.ByteSize();
92 while (mUsedInBytes + protoSize > mSizeInBytes) {
93 if (mStorage.empty()) {
94 return;
95 }
96 mUsedInBytes -= mStorage.front().ByteSize();
97 mStorage.pop();
98 }
99 mUsedInBytes += protoSize;
100 mStorage.emplace();
101 mStorage.back().Swap(&proto);
102}
103
104void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
105 fileProto->mutable_entry()->Reserve(mStorage.size());
106
107 while (!mStorage.empty()) {
108 auto entry = fileProto->add_entry();
109 entry->Swap(&mStorage.front());
110 mStorage.pop();
111 }
112}
113
Nataniel Borges2b796da2019-02-15 13:32:18 -0800114void SurfaceTracing::enable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700115 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700116
Adrian Roos1e1a1282017-11-01 19:05:31 +0100117 if (mEnabled) {
118 return;
119 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800120 mBuffer.reset(mBufferSize);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100121 mEnabled = true;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800122 mThread = std::thread(&SurfaceTracing::mainLoop, this);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100123}
124
Nataniel Borges2b796da2019-02-15 13:32:18 -0800125status_t SurfaceTracing::writeToFile() {
126 mThread.join();
127 return mLastErr;
128}
129
130bool SurfaceTracing::disable() {
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) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800134 return false;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100135 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800136
Adrian Roos1e1a1282017-11-01 19:05:31 +0100137 mEnabled = false;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800138 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700139 mCanStartTrace.notify_all();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800140 return true;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100141}
142
Yichi Chenadc69612018-09-15 14:51:18 +0800143bool SurfaceTracing::isEnabled() const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700144 std::scoped_lock lock(mTraceLock);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100145 return mEnabled;
146}
147
Nataniel Borges2b796da2019-02-15 13:32:18 -0800148void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700149 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800150 mBufferSize = bufferSizeInByte;
151 mBuffer.setSize(bufferSizeInByte);
152}
153
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700154void SurfaceTracing::setTraceFlags(uint32_t flags) {
155 std::scoped_lock lock(mSfLock);
156 mTraceFlags = flags;
157}
158
Nataniel Borges2b796da2019-02-15 13:32:18 -0800159LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
160 ATRACE_CALL();
Yichi Chenadc69612018-09-15 14:51:18 +0800161
Yichi Chen9c696ed2018-10-01 22:32:30 +0800162 LayersTraceProto entry;
163 entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
164 entry.set_where(where);
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700165 LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags));
Yichi Chen9c696ed2018-10-01 22:32:30 +0800166 entry.mutable_layers()->Swap(&layers);
167
Nataniel Borges2b796da2019-02-15 13:32:18 -0800168 return entry;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100169}
170
Nataniel Borges2b796da2019-02-15 13:32:18 -0800171void SurfaceTracing::writeProtoFileLocked() {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100172 ATRACE_CALL();
173
Yichi Chen9c696ed2018-10-01 22:32:30 +0800174 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100175 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800176
177 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
178 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
179 mBuffer.flush(&fileProto);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800180 mBuffer.reset(mBufferSize);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800181
182 if (!fileProto.SerializeToString(&output)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800183 ALOGE("Could not save the proto file! Permission denied");
184 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100185 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800186 if (!android::base::WriteStringToFile(output, kDefaultFileName, S_IRWXU | S_IRGRP, getuid(),
187 getgid(), true)) {
188 ALOGE("Could not save the proto file! There are missing fields");
189 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100190 }
191
Nataniel Borges2b796da2019-02-15 13:32:18 -0800192 mLastErr = NO_ERROR;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100193}
194
Yiwei Zhang5434a782018-12-05 18:06:32 -0800195void SurfaceTracing::dump(std::string& result) const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700196 std::scoped_lock lock(mTraceLock);
Yiwei Zhang5434a782018-12-05 18:06:32 -0800197 base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
198 base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
199 mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
200 float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800201}
202
Adrian Roos1e1a1282017-11-01 19:05:31 +0100203} // namespace android