1 /*
2  * Copyright (C) 2018 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 
17 #include <android-base/file.h>
18 #include <android-base/logging.h>
19 #include <android-base/stringprintf.h>
20 
21 #include "AtraceDevice.h"
22 
23 namespace android {
24 namespace hardware {
25 namespace atrace {
26 namespace V1_0 {
27 namespace implementation {
28 
29 using ::android::hardware::atrace::V1_0::Status;
30 using ::android::hardware::atrace::V1_0::TracingCategory;
31 
32 struct TracingConfig {
33     std::string description;
34     // path and if error on failure
35     std::vector<std::pair<std::string, bool>> paths;
36 };
37 
38 // This is a map stores categories and their sysfs paths with required flags
39 const std::map<std::string, TracingConfig> kTracingMap = {
40         // gfx
41         {
42                 "gfx",
43                 {"Graphics", {{"mdss", false}, {"sde", false}, {"mali_systrace", false}}},
44         },
45         {
46                 "ion",
47                 {"ION allocation", {{"kmem/ion_alloc_buffer_start", false}}},
48         },
49 };
50 
51 // Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow.
listCategories(listCategories_cb _hidl_cb)52 Return<void> AtraceDevice::listCategories(listCategories_cb _hidl_cb) {
53     hidl_vec<TracingCategory> categories;
54     categories.resize(kTracingMap.size());
55     std::size_t i = 0;
56     for (auto& c : kTracingMap) {
57         categories[i].name = c.first;
58         categories[i].description = c.second.description;
59         i++;
60     }
61     _hidl_cb(categories);
62     return Void();
63 }
64 
AtraceDevice()65 AtraceDevice::AtraceDevice() {
66     struct stat st;
67 
68     tracefs_event_root_ = "/sys/kernel/tracing/events/";
69     if (stat(tracefs_event_root_.c_str(), &st) != 0) {
70         tracefs_event_root_ = "/sys/kernel/debug/tracing/events/";
71         CHECK(stat(tracefs_event_root_.c_str(), &st) == 0) << "tracefs must be mounted at either"
72                                                               "/sys/kernel/tracing or "
73                                                               "/sys/kernel/debug/tracing";
74     }
75 }
76 
enableCategories(const hidl_vec<hidl_string> & categories)77 Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::enableCategories(
78         const hidl_vec<hidl_string>& categories) {
79     if (!categories.size()) {
80         return Status::ERROR_INVALID_ARGUMENT;
81     }
82 
83     for (auto& c : categories) {
84         if (kTracingMap.count(c)) {
85             for (auto& p : kTracingMap.at(c).paths) {
86                 std::string tracefs_event_enable_path = android::base::StringPrintf(
87                         "%s%s/enable", tracefs_event_root_.c_str(), p.first.c_str());
88                 if (!android::base::WriteStringToFile("1", tracefs_event_enable_path)) {
89                     LOG(ERROR) << "Failed to enable tracing on: " << tracefs_event_enable_path;
90                     if (p.second) {
91                         // disable before return
92                         disableAllCategories();
93                         return Status::ERROR_TRACING_POINT;
94                     }
95                 }
96             }
97         } else {
98             return Status::ERROR_INVALID_ARGUMENT;
99         }
100     }
101     return Status::SUCCESS;
102 }
103 
disableAllCategories()104 Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::disableAllCategories() {
105     auto ret = Status::SUCCESS;
106 
107     for (auto& c : kTracingMap) {
108         for (auto& p : c.second.paths) {
109             std::string tracefs_event_enable_path = android::base::StringPrintf(
110                     "%s%s/enable", tracefs_event_root_.c_str(), p.first.c_str());
111             if (!android::base::WriteStringToFile("0", tracefs_event_enable_path)) {
112                 LOG(ERROR) << "Failed to disable tracing on: " << tracefs_event_enable_path;
113                 if (p.second) {
114                     ret = Status::ERROR_TRACING_POINT;
115                 }
116             }
117         }
118     }
119     return ret;
120 }
121 
122 }  // namespace implementation
123 }  // namespace V1_0
124 }  // namespace atrace
125 }  // namespace hardware
126 }  // namespace android
127