blob: 6fd4e46c730aa8704c5bc916aafa39f2b8b4e0de [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() {
48 LayersTraceProto entry;
49 {
50 std::scoped_lock lock(mSfLock);
51 entry = traceLayersLocked("tracing.enable");
52 }
53 addTraceToBuffer(entry);
54}
55
56LayersTraceProto SurfaceTracing::traceWhenNotified() {
57 std::unique_lock<std::mutex> lock(mSfLock);
58 mCanStartTrace.wait(lock);
59 android::base::ScopedLockAssertion assumeLock(mSfLock);
60 LayersTraceProto entry = traceLayersLocked(mWhere);
61 lock.unlock();
62 return entry;
63}
64
65bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) {
66 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080067 mBuffer.emplace(std::move(entry));
Vishnu Nair9245d3b2019-03-22 13:38:56 -070068 if (mWriteToFile) {
69 writeProtoFileLocked();
70 mWriteToFile = false;
71 }
72 return mEnabled;
Nataniel Borges2b796da2019-02-15 13:32:18 -080073}
74
75void SurfaceTracing::notify(const char* where) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070076 std::scoped_lock lock(mSfLock);
Vishnu Nairb0159482019-03-18 12:48:46 -070077 mWhere = where;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070078 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080079}
80
81void SurfaceTracing::writeToFileAsync() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -070082 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -080083 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -070084 mCanStartTrace.notify_one();
Nataniel Borges2b796da2019-02-15 13:32:18 -080085}
86
Yichi Chen9c696ed2018-10-01 22:32:30 +080087void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
88 // use the swap trick to make sure memory is released
89 std::queue<LayersTraceProto>().swap(mStorage);
90 mSizeInBytes = newSize;
91 mUsedInBytes = 0U;
92}
93
94void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
95 auto protoSize = proto.ByteSize();
96 while (mUsedInBytes + protoSize > mSizeInBytes) {
97 if (mStorage.empty()) {
98 return;
99 }
100 mUsedInBytes -= mStorage.front().ByteSize();
101 mStorage.pop();
102 }
103 mUsedInBytes += protoSize;
104 mStorage.emplace();
105 mStorage.back().Swap(&proto);
106}
107
108void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
109 fileProto->mutable_entry()->Reserve(mStorage.size());
110
111 while (!mStorage.empty()) {
112 auto entry = fileProto->add_entry();
113 entry->Swap(&mStorage.front());
114 mStorage.pop();
115 }
116}
117
Nataniel Borges2b796da2019-02-15 13:32:18 -0800118void SurfaceTracing::enable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700119 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700120
Adrian Roos1e1a1282017-11-01 19:05:31 +0100121 if (mEnabled) {
122 return;
123 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800124 mBuffer.reset(mBufferSize);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100125 mEnabled = true;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800126 mThread = std::thread(&SurfaceTracing::mainLoop, this);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100127}
128
Nataniel Borges2b796da2019-02-15 13:32:18 -0800129status_t SurfaceTracing::writeToFile() {
130 mThread.join();
131 return mLastErr;
132}
133
134bool SurfaceTracing::disable() {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700135 std::scoped_lock lock(mTraceLock);
Chia-I Wua3e7ddc2018-09-20 11:42:46 -0700136
Adrian Roos1e1a1282017-11-01 19:05:31 +0100137 if (!mEnabled) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800138 return false;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100139 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800140
Adrian Roos1e1a1282017-11-01 19:05:31 +0100141 mEnabled = false;
Nataniel Borges2b796da2019-02-15 13:32:18 -0800142 mWriteToFile = true;
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700143 mCanStartTrace.notify_all();
Nataniel Borges2b796da2019-02-15 13:32:18 -0800144 return true;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100145}
146
Yichi Chenadc69612018-09-15 14:51:18 +0800147bool SurfaceTracing::isEnabled() const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700148 std::scoped_lock lock(mTraceLock);
Adrian Roos1e1a1282017-11-01 19:05:31 +0100149 return mEnabled;
150}
151
Nataniel Borges2b796da2019-02-15 13:32:18 -0800152void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700153 std::scoped_lock lock(mTraceLock);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800154 mBufferSize = bufferSizeInByte;
155 mBuffer.setSize(bufferSizeInByte);
156}
157
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700158void SurfaceTracing::setTraceFlags(uint32_t flags) {
159 std::scoped_lock lock(mSfLock);
160 mTraceFlags = flags;
161}
162
Nataniel Borges2b796da2019-02-15 13:32:18 -0800163LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
164 ATRACE_CALL();
Yichi Chenadc69612018-09-15 14:51:18 +0800165
Yichi Chen9c696ed2018-10-01 22:32:30 +0800166 LayersTraceProto entry;
167 entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
168 entry.set_where(where);
Vishnu Nair8406fd72019-07-30 11:29:31 -0700169 LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
Vishnu Nair0f085c62019-08-30 08:49:12 -0700170 mFlinger.dumpOffscreenLayersProto(layers);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800171 entry.mutable_layers()->Swap(&layers);
172
Nataniel Borges2b796da2019-02-15 13:32:18 -0800173 return entry;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100174}
175
Nataniel Borges2b796da2019-02-15 13:32:18 -0800176void SurfaceTracing::writeProtoFileLocked() {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100177 ATRACE_CALL();
178
Yichi Chen9c696ed2018-10-01 22:32:30 +0800179 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100180 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800181
182 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
183 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
184 mBuffer.flush(&fileProto);
Nataniel Borges2b796da2019-02-15 13:32:18 -0800185 mBuffer.reset(mBufferSize);
Yichi Chen9c696ed2018-10-01 22:32:30 +0800186
187 if (!fileProto.SerializeToString(&output)) {
Nataniel Borges2b796da2019-02-15 13:32:18 -0800188 ALOGE("Could not save the proto file! Permission denied");
189 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100190 }
Nataniel Borges2b796da2019-02-15 13:32:18 -0800191 if (!android::base::WriteStringToFile(output, kDefaultFileName, S_IRWXU | S_IRGRP, getuid(),
192 getgid(), true)) {
193 ALOGE("Could not save the proto file! There are missing fields");
194 mLastErr = PERMISSION_DENIED;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100195 }
196
Nataniel Borges2b796da2019-02-15 13:32:18 -0800197 mLastErr = NO_ERROR;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100198}
199
Yiwei Zhang5434a782018-12-05 18:06:32 -0800200void SurfaceTracing::dump(std::string& result) const {
Vishnu Nair9245d3b2019-03-22 13:38:56 -0700201 std::scoped_lock lock(mTraceLock);
Yiwei Zhang5434a782018-12-05 18:06:32 -0800202 base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
203 base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
204 mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
205 float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800206}
207
Adrian Roos1e1a1282017-11-01 19:05:31 +0100208} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800209
210// TODO(b/129481165): remove the #pragma below and fix conversion issues
211#pragma clang diagnostic pop // ignored "-Wconversion"