/* * Copyright (C) 2019 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. */ #include #include #include #include "AtraceDevice.h" namespace android { namespace hardware { namespace atrace { namespace V1_0 { namespace implementation { using ::android::hardware::atrace::V1_0::Status; using ::android::hardware::atrace::V1_0::TracingCategory; struct TracingConfig { std::string description; // path and if error on failure std::vector> paths; }; // This is a map stores categories and their tracefs event name with required flags const std::map kTracingMap = { { "gfx", {"Graphics", {{"mdss", false}, {"sde", false}, {"dpu", false}, {"g2d", false}, {"mali", false}}}, }, { "memory", {"Memory", {{"fastrpc/fastrpc_dma_stat", false}, {"dmabuf_heap", false}}}, }, { "ion", {"ION Allocation", {{"kmem/ion_alloc_buffer_start", false}}}, }, { "sched", {"CPU Scheduling and Trustzone", {{"scm", false}, {"systrace", false}}}, }, { "freq", {"CPU Frequency and System Clock", {{"msm_bus", false}}}, }, { "thermal_tj", {"Tj power limits and frequency", {{"lmh/lmh_dcvs_freq", false}, {"thermal_exynos", false}, {"thermal_exynos_gpu", false}}}, }, }; // Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow. Return AtraceDevice::listCategories(listCategories_cb _hidl_cb) { hidl_vec categories; categories.resize(kTracingMap.size()); std::size_t i = 0; for (auto &c : kTracingMap) { categories[i].name = c.first; categories[i].description = c.second.description; i++; } _hidl_cb(categories); return Void(); } AtraceDevice::AtraceDevice() { struct stat st; mTracefsEventRoot = "/sys/kernel/tracing/events/"; if (stat(mTracefsEventRoot.c_str(), &st) != 0) { mTracefsEventRoot = "/sys/kernel/debug/tracing/events/"; CHECK(stat(mTracefsEventRoot.c_str(), &st) == 0) << "tracefs must be mounted at either" "/sys/kernel/tracing or " "/sys/kernel/debug/tracing"; } } Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::enableCategories( const hidl_vec &categories) { if (!categories.size()) { return Status::ERROR_INVALID_ARGUMENT; } for (auto &c : categories) { if (kTracingMap.count(c)) { for (auto &p : kTracingMap.at(c).paths) { std::string tracefs_event_enable_path = android::base::StringPrintf( "%s%s/enable", mTracefsEventRoot.c_str(), p.first.c_str()); if (!android::base::WriteStringToFile("1", tracefs_event_enable_path)) { LOG(ERROR) << "Failed to enable tracing on: " << tracefs_event_enable_path; if (p.second) { // disable before return disableAllCategories(); return Status::ERROR_TRACING_POINT; } } } } else { return Status::ERROR_INVALID_ARGUMENT; } } return Status::SUCCESS; } Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::disableAllCategories() { auto ret = Status::SUCCESS; for (auto &c : kTracingMap) { for (auto &p : c.second.paths) { std::string tracefs_event_enable_path = android::base::StringPrintf( "%s%s/enable", mTracefsEventRoot.c_str(), p.first.c_str()); if (!android::base::WriteStringToFile("0", tracefs_event_enable_path)) { LOG(ERROR) << "Failed to disable tracing on: " << tracefs_event_enable_path; if (p.second) { ret = Status::ERROR_TRACING_POINT; } } } } return ret; } } // namespace implementation } // namespace V1_0 } // namespace atrace } // namespace hardware } // namespace android