blob: 1835929940c24a8c4f4745d98ddedec16f0c538e [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>
23#include <log/log.h>
24#include <utils/SystemClock.h>
25#include <utils/Trace.h>
26
27namespace android {
28
Yichi Chen9c696ed2018-10-01 22:32:30 +080029void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
30 // use the swap trick to make sure memory is released
31 std::queue<LayersTraceProto>().swap(mStorage);
32 mSizeInBytes = newSize;
33 mUsedInBytes = 0U;
34}
35
36void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
37 auto protoSize = proto.ByteSize();
38 while (mUsedInBytes + protoSize > mSizeInBytes) {
39 if (mStorage.empty()) {
40 return;
41 }
42 mUsedInBytes -= mStorage.front().ByteSize();
43 mStorage.pop();
44 }
45 mUsedInBytes += protoSize;
46 mStorage.emplace();
47 mStorage.back().Swap(&proto);
48}
49
50void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
51 fileProto->mutable_entry()->Reserve(mStorage.size());
52
53 while (!mStorage.empty()) {
54 auto entry = fileProto->add_entry();
55 entry->Swap(&mStorage.front());
56 mStorage.pop();
57 }
58}
59
60void SurfaceTracing::enable(size_t bufferSizeInByte) {
Chia-I Wua3e7ddc2018-09-20 11:42:46 -070061 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
62
Adrian Roos1e1a1282017-11-01 19:05:31 +010063 if (mEnabled) {
64 return;
65 }
Adrian Roos1e1a1282017-11-01 19:05:31 +010066 mEnabled = true;
Yichi Chen9c696ed2018-10-01 22:32:30 +080067 mBuffer.reset(bufferSizeInByte);
Adrian Roos1e1a1282017-11-01 19:05:31 +010068}
69
70status_t SurfaceTracing::disable() {
Chia-I Wua3e7ddc2018-09-20 11:42:46 -070071 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
72
Adrian Roos1e1a1282017-11-01 19:05:31 +010073 if (!mEnabled) {
74 return NO_ERROR;
75 }
Adrian Roos1e1a1282017-11-01 19:05:31 +010076 mEnabled = false;
77 status_t err(writeProtoFileLocked());
78 ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied");
79 ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields");
Yichi Chen9c696ed2018-10-01 22:32:30 +080080 mBuffer.reset(0);
Adrian Roos1e1a1282017-11-01 19:05:31 +010081 return err;
82}
83
Yichi Chenadc69612018-09-15 14:51:18 +080084bool SurfaceTracing::isEnabled() const {
Chia-I Wua3e7ddc2018-09-20 11:42:46 -070085 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
Adrian Roos1e1a1282017-11-01 19:05:31 +010086 return mEnabled;
87}
88
89void SurfaceTracing::traceLayers(const char* where, LayersProto layers) {
90 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
Vishnu Nairf770fcc2018-06-12 14:39:30 -070091 if (!mEnabled) {
92 return;
93 }
Yichi Chenadc69612018-09-15 14:51:18 +080094
Yichi Chen9c696ed2018-10-01 22:32:30 +080095 LayersTraceProto entry;
96 entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
97 entry.set_where(where);
98 entry.mutable_layers()->Swap(&layers);
99
100 mBuffer.emplace(std::move(entry));
Adrian Roos1e1a1282017-11-01 19:05:31 +0100101}
102
103status_t SurfaceTracing::writeProtoFileLocked() {
104 ATRACE_CALL();
105
Yichi Chen9c696ed2018-10-01 22:32:30 +0800106 LayersTraceFileProto fileProto;
Adrian Roos1e1a1282017-11-01 19:05:31 +0100107 std::string output;
Yichi Chen9c696ed2018-10-01 22:32:30 +0800108
109 fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
110 LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
111 mBuffer.flush(&fileProto);
112
113 if (!fileProto.SerializeToString(&output)) {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100114 return PERMISSION_DENIED;
115 }
Yichi Chen9c696ed2018-10-01 22:32:30 +0800116 if (!android::base::WriteStringToFile(output, kDefaultFileName, true)) {
Adrian Roos1e1a1282017-11-01 19:05:31 +0100117 return PERMISSION_DENIED;
118 }
119
120 return NO_ERROR;
121}
122
Yichi Chenadc69612018-09-15 14:51:18 +0800123void SurfaceTracing::dump(String8& result) const {
124 std::lock_guard<std::mutex> protoGuard(mTraceMutex);
125
126 result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
Yichi Chen9c696ed2018-10-01 22:32:30 +0800127 result.appendFormat(" number of entries: %zu (%.2fMB / %.2fMB)\n", mBuffer.frameCount(),
128 float(mBuffer.used()) / float(1_MB), float(mBuffer.size()) / float(1_MB));
Yichi Chenadc69612018-09-15 14:51:18 +0800129}
130
Adrian Roos1e1a1282017-11-01 19:05:31 +0100131} // namespace android