3 ** Copyright 2017, The Android Open Source Project
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
18 #ifndef SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_BINDER_H_
19 #define SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_BINDER_H_
31 #include <android-base/logging.h>
32 #include <android-base/stringprintf.h>
33 #include <binder/BinderService.h>
34 #include <binder/IResultReceiver.h>
35 #include <binder/Status.h>
36 #include <utils/String16.h>
37 #include <utils/String8.h>
38 #include <utils/Vector.h>
40 #include "android/os/BnPerfProfd.h"
43 #include "configreader.h"
44 #include "perfprofdcore.h"
49 class PerfProfdNativeService : public BinderService<PerfProfdNativeService>,
50 public os::BnPerfProfd {
52 struct BinderConfig : public Config {
53 bool is_profiling = false;
55 void Sleep(size_t seconds) override {
56 // TODO: Replace with condition_variable::wait ...
62 static status_t start() {
63 IPCThreadState::self()->disableBackgroundScheduling(true);
64 status_t ret = BinderService<PerfProfdNativeService>::publish();
65 if (ret != android::OK) {
68 sp<ProcessState> ps(ProcessState::self());
69 ps->startThreadPool();
70 ps->giveThreadPoolName();
74 static char const* getServiceName() { return "perfprofd"; }
76 status_t dump(int fd, const Vector<String16> &args) override {
77 auto out = std::fstream(base::StringPrintf("/proc/self/fd/%d", fd));
78 out << "Nothing to log, yet!" << std::endl;
83 binder::Status startProfiling(int32_t profilingDuration,
84 int32_t profilingInterval,
85 int32_t iterations) override {
86 std::lock_guard<std::mutex> guard(lock_);
88 if (cur_config_.is_profiling) {
89 // TODO: Define error code?
90 return binder::Status::fromServiceSpecificError(1);
92 cur_config_.is_profiling = true;
94 ConfigReader().FillConfig(&cur_config_); // Create a default config.
96 cur_config_.sample_duration_in_s = static_cast<uint32_t>(profilingDuration);
97 cur_config_.collection_interval_in_s = static_cast<uint32_t>(profilingInterval);
98 cur_config_.main_loop_iterations = static_cast<uint32_t>(iterations);
100 auto profile_runner = [](PerfProfdNativeService* service) {
101 ProfilingLoop(service->cur_config_);
103 // This thread is done.
104 std::lock_guard<std::mutex> unset_guard(service->lock_);
105 service->cur_config_.is_profiling = false;
107 std::thread profiling_thread(profile_runner, this);
108 profiling_thread.detach(); // Let it go.
110 return binder::Status::ok();
113 binder::Status stopProfiling() override {
114 UNIMPLEMENTED(ERROR) << "stopProfiling: To be implemented";
115 return binder::Status::fromExceptionCode(1);
118 // Override onTransact so we can handle shellCommand.
119 status_t onTransact(uint32_t _aidl_code,
120 const Parcel& _aidl_data,
122 uint32_t _aidl_flags = 0) override {
123 switch (_aidl_code) {
124 case IBinder::SHELL_COMMAND_TRANSACTION: {
125 int in = _aidl_data.readFileDescriptor();
126 int out = _aidl_data.readFileDescriptor();
127 int err = _aidl_data.readFileDescriptor();
128 int argc = _aidl_data.readInt32();
129 Vector<String16> args;
130 for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) {
131 args.add(_aidl_data.readString16());
133 sp<IBinder> unusedCallback;
134 sp<IResultReceiver> resultReceiver;
136 if ((status = _aidl_data.readNullableStrongBinder(&unusedCallback)) != OK)
138 if ((status = _aidl_data.readNullableStrongBinder(&resultReceiver)) != OK)
140 status = shellCommand(in, out, err, args);
141 if (resultReceiver != nullptr) {
142 resultReceiver->send(status);
148 return BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
153 status_t shellCommand(int /*in*/, int out, int err, Vector<String16>& args) {
154 if (android::base::kEnableDChecks) {
155 LOG(VERBOSE) << "Perfprofd::shellCommand";
157 for (size_t i = 0, n = args.size(); i < n; i++) {
158 LOG(VERBOSE) << " arg[" << i << "]: '" << String8(args[i]).string() << "'";
162 if (args.size() >= 1) {
163 if (args[0] == String16("dump")) {
166 } else if (args[0] == String16("startProfiling")) {
167 if (args.size() < 4) {
170 // TODO: handle invalid strings.
171 int32_t duration = strtol(String8(args[1]).string(), nullptr, 0);
172 int32_t interval = strtol(String8(args[2]).string(), nullptr, 0);
173 int32_t iterations = strtol(String8(args[3]).string(), nullptr, 0);
174 binder::Status status = startProfiling(duration, interval, iterations);
178 return status.serviceSpecificErrorCode();
180 } else if (args[0] == String16("stopProfiling")) {
181 binder::Status status = stopProfiling();
185 return status.serviceSpecificErrorCode();
194 BinderConfig cur_config_;
197 } // namespace perfprofd
198 } // namespace android
200 #endif // SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_BINDER_H_