| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 1 | /* | 
|  | 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 Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 21 | #include <SurfaceFlinger.h> | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 22 |  | 
|  | 23 | #include <android-base/file.h> | 
| Yiwei Zhang | 5434a78 | 2018-12-05 18:06:32 -0800 | [diff] [blame] | 24 | #include <android-base/stringprintf.h> | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 25 | #include <log/log.h> | 
|  | 26 | #include <utils/SystemClock.h> | 
|  | 27 | #include <utils/Trace.h> | 
|  | 28 |  | 
|  | 29 | namespace android { | 
|  | 30 |  | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 31 | SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger) | 
|  | 32 | : mFlinger(flinger), mSfLock(flinger.mDrawingStateLock) {} | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 33 |  | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 34 | void SurfaceTracing::mainLoop() { | 
|  | 35 | addFirstEntry(); | 
|  | 36 | bool enabled = true; | 
|  | 37 | while (enabled) { | 
|  | 38 | LayersTraceProto entry = traceWhenNotified(); | 
|  | 39 | enabled = addTraceToBuffer(entry); | 
|  | 40 | } | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 41 | } | 
|  | 42 |  | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 43 | void SurfaceTracing::addFirstEntry() { | 
|  | 44 | LayersTraceProto entry; | 
|  | 45 | { | 
|  | 46 | std::scoped_lock lock(mSfLock); | 
|  | 47 | entry = traceLayersLocked("tracing.enable"); | 
|  | 48 | } | 
|  | 49 | addTraceToBuffer(entry); | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | LayersTraceProto 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 |  | 
|  | 61 | bool SurfaceTracing::addTraceToBuffer(LayersTraceProto& entry) { | 
|  | 62 | std::scoped_lock lock(mTraceLock); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 63 | mBuffer.emplace(std::move(entry)); | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 64 | if (mWriteToFile) { | 
|  | 65 | writeProtoFileLocked(); | 
|  | 66 | mWriteToFile = false; | 
|  | 67 | } | 
|  | 68 | return mEnabled; | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 69 | } | 
|  | 70 |  | 
|  | 71 | void SurfaceTracing::notify(const char* where) { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 72 | std::scoped_lock lock(mSfLock); | 
| Vishnu Nair | b015948 | 2019-03-18 12:48:46 -0700 | [diff] [blame] | 73 | mWhere = where; | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 74 | mCanStartTrace.notify_one(); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 75 | } | 
|  | 76 |  | 
|  | 77 | void SurfaceTracing::writeToFileAsync() { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 78 | std::scoped_lock lock(mTraceLock); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 79 | mWriteToFile = true; | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 80 | mCanStartTrace.notify_one(); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 81 | } | 
|  | 82 |  | 
| Yichi Chen | 9c696ed | 2018-10-01 22:32:30 +0800 | [diff] [blame] | 83 | void 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 |  | 
|  | 90 | void 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 |  | 
|  | 104 | void 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 Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 114 | void SurfaceTracing::enable() { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 115 | std::scoped_lock lock(mTraceLock); | 
| Chia-I Wu | a3e7ddc | 2018-09-20 11:42:46 -0700 | [diff] [blame] | 116 |  | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 117 | if (mEnabled) { | 
|  | 118 | return; | 
|  | 119 | } | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 120 | mBuffer.reset(mBufferSize); | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 121 | mEnabled = true; | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 122 | mThread = std::thread(&SurfaceTracing::mainLoop, this); | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 123 | } | 
|  | 124 |  | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 125 | status_t SurfaceTracing::writeToFile() { | 
|  | 126 | mThread.join(); | 
|  | 127 | return mLastErr; | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | bool SurfaceTracing::disable() { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 131 | std::scoped_lock lock(mTraceLock); | 
| Chia-I Wu | a3e7ddc | 2018-09-20 11:42:46 -0700 | [diff] [blame] | 132 |  | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 133 | if (!mEnabled) { | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 134 | return false; | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 135 | } | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 136 |  | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 137 | mEnabled = false; | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 138 | mWriteToFile = true; | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 139 | mCanStartTrace.notify_all(); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 140 | return true; | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 141 | } | 
|  | 142 |  | 
| Yichi Chen | adc6961 | 2018-09-15 14:51:18 +0800 | [diff] [blame] | 143 | bool SurfaceTracing::isEnabled() const { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 144 | std::scoped_lock lock(mTraceLock); | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 145 | return mEnabled; | 
|  | 146 | } | 
|  | 147 |  | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 148 | void SurfaceTracing::setBufferSize(size_t bufferSizeInByte) { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 149 | std::scoped_lock lock(mTraceLock); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 150 | mBufferSize = bufferSizeInByte; | 
|  | 151 | mBuffer.setSize(bufferSizeInByte); | 
|  | 152 | } | 
|  | 153 |  | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 154 | void SurfaceTracing::setTraceFlags(uint32_t flags) { | 
|  | 155 | std::scoped_lock lock(mSfLock); | 
|  | 156 | mTraceFlags = flags; | 
|  | 157 | } | 
|  | 158 |  | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 159 | LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) { | 
|  | 160 | ATRACE_CALL(); | 
| Yichi Chen | adc6961 | 2018-09-15 14:51:18 +0800 | [diff] [blame] | 161 |  | 
| Yichi Chen | 9c696ed | 2018-10-01 22:32:30 +0800 | [diff] [blame] | 162 | LayersTraceProto entry; | 
|  | 163 | entry.set_elapsed_realtime_nanos(elapsedRealtimeNano()); | 
|  | 164 | entry.set_where(where); | 
| Vishnu Nair | 8406fd7 | 2019-07-30 11:29:31 -0700 | [diff] [blame] | 165 | LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags)); | 
| Vishnu Nair | 0f085c6 | 2019-08-30 08:49:12 -0700 | [diff] [blame] | 166 | mFlinger.dumpOffscreenLayersProto(layers); | 
| Yichi Chen | 9c696ed | 2018-10-01 22:32:30 +0800 | [diff] [blame] | 167 | entry.mutable_layers()->Swap(&layers); | 
|  | 168 |  | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 169 | return entry; | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 170 | } | 
|  | 171 |  | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 172 | void SurfaceTracing::writeProtoFileLocked() { | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 173 | ATRACE_CALL(); | 
|  | 174 |  | 
| Yichi Chen | 9c696ed | 2018-10-01 22:32:30 +0800 | [diff] [blame] | 175 | LayersTraceFileProto fileProto; | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 176 | std::string output; | 
| Yichi Chen | 9c696ed | 2018-10-01 22:32:30 +0800 | [diff] [blame] | 177 |  | 
|  | 178 | fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | | 
|  | 179 | LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); | 
|  | 180 | mBuffer.flush(&fileProto); | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 181 | mBuffer.reset(mBufferSize); | 
| Yichi Chen | 9c696ed | 2018-10-01 22:32:30 +0800 | [diff] [blame] | 182 |  | 
|  | 183 | if (!fileProto.SerializeToString(&output)) { | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 184 | ALOGE("Could not save the proto file! Permission denied"); | 
|  | 185 | mLastErr = PERMISSION_DENIED; | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 186 | } | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 187 | 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 Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 191 | } | 
|  | 192 |  | 
| Nataniel Borges | 2b796da | 2019-02-15 13:32:18 -0800 | [diff] [blame] | 193 | mLastErr = NO_ERROR; | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 194 | } | 
|  | 195 |  | 
| Yiwei Zhang | 5434a78 | 2018-12-05 18:06:32 -0800 | [diff] [blame] | 196 | void SurfaceTracing::dump(std::string& result) const { | 
| Vishnu Nair | 9245d3b | 2019-03-22 13:38:56 -0700 | [diff] [blame] | 197 | std::scoped_lock lock(mTraceLock); | 
| Yiwei Zhang | 5434a78 | 2018-12-05 18:06:32 -0800 | [diff] [blame] | 198 | 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 Chen | adc6961 | 2018-09-15 14:51:18 +0800 | [diff] [blame] | 202 | } | 
|  | 203 |  | 
| Adrian Roos | 1e1a128 | 2017-11-01 19:05:31 +0100 | [diff] [blame] | 204 | } // namespace android |