blob: 5d9be0b8a91e4b4722507ab23ff7263a858f0b8f [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
Nataniel Borgesc4def152019-09-26 15:20:00 +020071void SurfaceTracing::notify(long compositionTime, const char* where) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070072 std::scoped_lock lock(mSfLock);
Nataniel Borgesc4def152019-09-26 15:20:00 +020073 mCompositionTime = compositionTime;
Vishnu Nairb0159482019-03-18 12:48:46 -070074 mWhere = where;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070075 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080076}
77
78void SurfaceTracing::writeToFileAsync() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070079 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080080 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070081 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080082}
83
Yichi Chen9c696ed2018-10-01 22:32:30 +080084void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
85 // use the swap trick to make sure memory is released
86 std::queue<LayersTraceProto>().swap(mStorage);
87 mSizeInBytes = newSize;
88 mUsedInBytes = 0U;
89}
90
91void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
92 auto protoSize = proto.ByteSize();
93 while (mUsedInBytes + protoSize > mSizeInBytes) {
94 if (mStorage.empty()) {
95 return;
96 }
97 mUsedInBytes -= mStorage.front().ByteSize();
98 mStorage.pop();
99 }
100 mUsedInBytes += protoSize;
101 mStorage.emplace();
102 mStorage.back().Swap(&proto);
103}
104
105void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
106 fileProto->mutable_entry()->Reserve(mStorage.size());
107
108 while (!mStorage.empty()) {
109 auto entry = fileProto->add_entry();
110 entry->Swap(&mStorage.front());
111 mStorage.pop();
112 }
113}
114
Nataniel Borges2b796da2019-02-15 13:32:18 -0800115void SurfaceTracing::enable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700116 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700117
Adrian Roos1e1a1282017-11-01 19:05:31 +0100118 if (mEnabled) {
119 return;
120 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800121 mBuffer.reset(mBufferSize);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100122 mEnabled = true;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800123 mThread = std::thread(&SurfaceTracing::mainLoop, this);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100124}
125
Nataniel Borges2b796da2019-02-15 13:32:18 -0800126status_t SurfaceTracing::writeToFile() {
127 mThread.join();
128 return mLastErr;
129}
130
131bool SurfaceTracing::disable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700132 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700133
Adrian Roos1e1a1282017-11-01 19:05:31 +0100134 if (!mEnabled) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800135 return false;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100136 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800137
Adrian Roos1e1a1282017-11-01 19:05:31 +0100138 mEnabled = false;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800139 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700140 mCanStartTrace.notify_all();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800141 return true;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100142}
143
Yichi Chenadc69612018-09-15 14:51:18 +0800144bool SurfaceTracing::isEnabled() const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700145 std::scoped_lock lock(mTraceLock);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100146 return mEnabled;
147}
148
Nataniel Borges2b796da2019-02-15 13:32:18 -0800149void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700150 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800151 mBufferSize = bufferSizeInByte;
152 mBuffer.setSize(bufferSizeInByte);
153}
154
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700155void SurfaceTracing::setTraceFlags(uint32_t flags) {
156 std::scoped_lock lock(mSfLock);
157 mTraceFlags = flags;
158}
159
Nataniel Borges2b796da2019-02-15 13:32:18 -0800160LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
161 ATRACE_CALL();
Yichi Chenadc69612018-09-15 14:51:18 +0800162
Yichi Chen9c696ed2018-10-01 22:32:30 +0800163 LayersTraceProto entry;
Nataniel Borgesc4def152019-09-26 15:20:00 +0200164 entry.set_elapsed_realtime_nanos(mCompositionTime);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800165 entry.set_where(where);
Vishnu Nairb57b01e2019-09-16 18:22:19 +0200166 LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
Yichi Chen9c696ed2018-10-01 22:32:30 +0800167 entry.mutable_layers()->Swap(&layers);
168
Nataniel Borges2b796da2019-02-15 13:32:18 -0800169 return entry;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100170}
171
Nataniel Borges2b796da2019-02-15 13:32:18 -0800172void SurfaceTracing::writeProtoFileLocked() {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100173 ATRACE_CALL();
174
Yichi Chen9c696ed2018-10-01 22:32:30 +0800175 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100176 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800177
178 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
179 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
180 mBuffer.flush(&fileProto);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800181 mBuffer.reset(mBufferSize);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800182
183 if (!fileProto.SerializeToString(&output)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800184 ALOGE("Could not save the proto file! Permission denied");
185 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100186 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800187 if (!android::base::WriteStringToFile(output, kDefaultFileName, S_IRWXU | S_IRGRP, getuid(),
188 getgid(), true)) {
189 ALOGE("Could not save the proto file! There are missing fields");
190 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100191 }
192
Nataniel Borges2b796da2019-02-15 13:32:18 -0800193 mLastErr = NO_ERROR;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100194}
195
Yiwei Zhang5434a782018-12-05 18:06:32 -0800196void SurfaceTracing::dump(std::string& result) const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700197 std::scoped_lock lock(mTraceLock);
Yiwei Zhang5434a782018-12-05 18:06:32 -0800198 base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
199 base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
200 mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
201 float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800202}
203
Adrian Roos1e1a1282017-11-01 19:05:31 +0100204} // namespace android