|  | /* | 
|  | * Copyright 2023 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #undef LOG_TAG | 
|  | #define LOG_TAG "LayerTracing" | 
|  |  | 
|  | #include "LayerDataSource.h" | 
|  |  | 
|  | #include <log/log.h> | 
|  | #include <perfetto/config/android/surfaceflinger_layers_config.pbzero.h> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | void LayerDataSource::Initialize(LayerTracing& layerTracing) { | 
|  | mLayerTracing.store(&layerTracing); | 
|  |  | 
|  | auto args = perfetto::TracingInitArgs{}; | 
|  | args.backends = perfetto::kSystemBackend; | 
|  | // We are tracing ~50kb/entry and the default shmem buffer size (256kb) could be overrun. | 
|  | // A shmem buffer overrun typically just stalls layer tracing, however when the stall | 
|  | // lasts for too long perfetto assumes there is a deadlock and aborts surfaceflinger. | 
|  | args.shmem_size_hint_kb = 1024; | 
|  | perfetto::Tracing::Initialize(args); | 
|  |  | 
|  | perfetto::DataSourceDescriptor descriptor; | 
|  | descriptor.set_name(android::LayerDataSource::kName); | 
|  | LayerDataSource::Register(descriptor); | 
|  | } | 
|  |  | 
|  | void LayerDataSource::UnregisterLayerTracing() { | 
|  | mLayerTracing.store(nullptr); | 
|  | } | 
|  |  | 
|  | void LayerDataSource::OnSetup(const LayerDataSource::SetupArgs& args) { | 
|  | const auto configRaw = args.config->surfaceflinger_layers_config_raw(); | 
|  | const auto config = perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Decoder{configRaw}; | 
|  |  | 
|  | if (config.has_mode() && config.mode() != LayerTracing::Mode::MODE_UNSPECIFIED) { | 
|  | mMode = static_cast<LayerTracing::Mode>(config.mode()); | 
|  | } else { | 
|  | mMode = LayerTracing::Mode::MODE_GENERATED; | 
|  | ALOGD("Received config with unspecified 'mode'. Using 'GENERATED' as default"); | 
|  | } | 
|  |  | 
|  | mFlags = 0; | 
|  | for (auto it = config.trace_flags(); it; ++it) { | 
|  | mFlags |= static_cast<uint32_t>(*it); | 
|  | } | 
|  | } | 
|  |  | 
|  | void LayerDataSource::OnStart(const LayerDataSource::StartArgs&) { | 
|  | ALOGD("Received OnStart event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags); | 
|  | if (auto* p = mLayerTracing.load()) { | 
|  | p->onStart(mMode, mFlags); | 
|  | } | 
|  | } | 
|  |  | 
|  | void LayerDataSource::OnFlush(const LayerDataSource::FlushArgs&) { | 
|  | ALOGD("Received OnFlush event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags); | 
|  | if (auto* p = mLayerTracing.load()) { | 
|  | p->onFlush(mMode, mFlags); | 
|  | } | 
|  | } | 
|  |  | 
|  | void LayerDataSource::OnStop(const LayerDataSource::StopArgs&) { | 
|  | ALOGD("Received OnStop event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags); | 
|  | if (auto* p = mLayerTracing.load()) { | 
|  | p->onStop(mMode); | 
|  | } | 
|  | } | 
|  |  | 
|  | LayerTracing::Mode LayerDataSource::GetMode() const { | 
|  | return mMode; | 
|  | } | 
|  |  | 
|  | std::atomic<LayerTracing*> LayerDataSource::mLayerTracing = nullptr; | 
|  |  | 
|  | } // namespace android | 
|  |  | 
|  | PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::LayerDataSource); |