blob: b7e9a915fa50d0a4d3e50bd62a27040372a2f5ba [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"
21
22#include <android-base/file.h>
Yiwei Zhang5434a782018-12-05 18:06:32 -080023#include <android-base/stringprintf.h>
Adrian Roos1e1a1282017-11-01 19:05:31 +010024#include <log/log.h>
25#include <utils/SystemClock.h>
26#include <utils/Trace.h>
27
28namespace android {
29
Yichi Chen9c696ed2018-10-01 22:32:30 +080030void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
31 // use the swap trick to make sure memory is released
32 std::queue<LayersTraceProto>().swap(mStorage);
33 mSizeInBytes = newSize;
34 mUsedInBytes = 0U;
35}
36
37void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
38 auto protoSize = proto.ByteSize();
39 while (mUsedInBytes + protoSize > mSizeInBytes) {
40 if (mStorage.empty()) {
41 return;
42 }
43 mUsedInBytes -= mStorage.front().ByteSize();
44 mStorage.pop();
45 }
46 mUsedInBytes += protoSize;
47 mStorage.emplace();
48 mStorage.back().Swap(&proto);
49}
50
51void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
52 fileProto->mutable_entry()->Reserve(mStorage.size());
53
54 while (!mStorage.empty()) {
55 auto entry = fileProto->add_entry();
56 entry->Swap(&mStorage.front());
57 mStorage.pop();
58 }
59}
60
61void SurfaceTracing::enable(size_t bufferSizeInByte) {
Chia-I Wua3e7ddc2018-09-20 11:42:46 -070062 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
63
Adrian Roos1e1a1282017-11-01 19:05:31 +010064 if (mEnabled) {
65 return;
66 }
Adrian Roos1e1a1282017-11-01 19:05:31 +010067 mEnabled = true;
Yichi Chen9c696ed2018-10-01 22:32:30 +080068 mBuffer.reset(bufferSizeInByte);
Adrian Roos1e1a1282017-11-01 19:05:31 +010069}
70
71status_t SurfaceTracing::disable() {
Chia-I Wua3e7ddc2018-09-20 11:42:46 -070072 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
73
Adrian Roos1e1a1282017-11-01 19:05:31 +010074 if (!mEnabled) {
75 return NO_ERROR;
76 }
Adrian Roos1e1a1282017-11-01 19:05:31 +010077 mEnabled = false;
78 status_t err(writeProtoFileLocked());
79 ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied");
80 ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields");
Yichi Chen9c696ed2018-10-01 22:32:30 +080081 mBuffer.reset(0);
Adrian Roos1e1a1282017-11-01 19:05:31 +010082 return err;
83}
84
Yichi Chenadc69612018-09-15 14:51:18 +080085bool SurfaceTracing::isEnabled() const {
Chia-I Wua3e7ddc2018-09-20 11:42:46 -070086 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
Adrian Roos1e1a1282017-11-01 19:05:31 +010087 return mEnabled;
88}
89
90void SurfaceTracing::traceLayers(const char* where, LayersProto layers) {
91 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
Vishnu Nairf770fcc2018-06-12 14:39:30 -070092 if (!mEnabled) {
93 return;
94 }
Yichi Chenadc69612018-09-15 14:51:18 +080095
Yichi Chen9c696ed2018-10-01 22:32:30 +080096 LayersTraceProto entry;
97 entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
98 entry.set_where(where);
99 entry.mutable_layers()->Swap(&layers);
100
101 mBuffer.emplace(std::move(entry));
Adrian Roos1e1a1282017-11-01 19:05:31 +0100102}
103
104status_t SurfaceTracing::writeProtoFileLocked() {
105 ATRACE_CALL();
106
Yichi Chen9c696ed2018-10-01 22:32:30 +0800107 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100108 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800109
110 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
111 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
112 mBuffer.flush(&fileProto);
113
114 if (!fileProto.SerializeToString(&output)) {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100115 return PERMISSION_DENIED;
116 }
Yichi Chen9c696ed2018-10-01 22:32:30 +0800117 if (!android::base::WriteStringToFile(output, kDefaultFileName, true)) {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100118 return PERMISSION_DENIED;
119 }
120
121 return NO_ERROR;
122}
123
Yiwei Zhang5434a782018-12-05 18:06:32 -0800124void SurfaceTracing::dump(std::string& result) const {
Yichi Chenadc69612018-09-15 14:51:18 +0800125 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
126
Yiwei Zhang5434a782018-12-05 18:06:32 -0800127 base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
128 base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
129 mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
130 float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800131}
132
Adrian Roos1e1a1282017-11-01 19:05:31 +0100133} // namespace android