| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 1 | /* |
| 2 | ** |
| 3 | ** Copyright 2017, The Android Open Source Project |
| 4 | ** |
| 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 |
| 8 | ** |
| 9 | ** http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | ** |
| 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. |
| 16 | */ |
| 17 | |
| 18 | #include "perfprofd_binder.h" |
| 19 | |
| Andreas Gampe | 28e3138 | 2018-03-19 16:24:14 -0700 | [diff] [blame] | 20 | #include <cstdio> |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 21 | #include <cstdlib> |
| 22 | #include <fstream> |
| 23 | #include <memory> |
| 24 | #include <mutex> |
| 25 | #include <string> |
| 26 | #include <thread> |
| 27 | |
| 28 | #include <inttypes.h> |
| 29 | #include <unistd.h> |
| 30 | |
| 31 | #include <android-base/logging.h> |
| 32 | #include <android-base/stringprintf.h> |
| Andreas Gampe | 9301b6f | 2018-04-27 15:15:34 -0700 | [diff] [blame] | 33 | #include <android-base/strings.h> |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 34 | #include <binder/BinderService.h> |
| 35 | #include <binder/IResultReceiver.h> |
| 36 | #include <binder/Status.h> |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 37 | #include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 38 | #include <utils/String16.h> |
| 39 | #include <utils/String8.h> |
| 40 | #include <utils/Vector.h> |
| 41 | |
| 42 | #include "android/os/BnPerfProfd.h" |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 43 | #include "perfprofd_config.pb.h" |
| Andreas Gampe | 0c09e0e | 2018-03-13 16:04:01 -0700 | [diff] [blame] | 44 | #include "perfprofd_record.pb.h" |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 45 | |
| 46 | #include "config.h" |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 47 | #include "configreader.h" |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 48 | #include "perfprofdcore.h" |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 49 | #include "perfprofd_threaded_handler.h" |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 50 | |
| 51 | namespace android { |
| 52 | namespace perfprofd { |
| 53 | namespace binder { |
| 54 | |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 55 | namespace { |
| 56 | |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 57 | using Status = ::android::binder::Status; |
| 58 | |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 59 | class PerfProfdNativeService : public BinderService<PerfProfdNativeService>, |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 60 | public ::android::os::BnPerfProfd, |
| 61 | public ThreadedHandler { |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 62 | public: |
| 63 | static status_t start(); |
| 64 | static int Main(); |
| 65 | |
| 66 | static char const* getServiceName() { return "perfprofd"; } |
| 67 | |
| 68 | status_t dump(int fd, const Vector<String16> &args) override; |
| 69 | |
| Andreas Gampe | 5a7181b | 2018-04-20 17:11:22 -0700 | [diff] [blame] | 70 | Status startProfiling(int32_t collectionInterval, |
| 71 | int32_t iterations, |
| 72 | int32_t process, |
| 73 | int32_t samplingPeriod, |
| 74 | int32_t samplingFrequency, |
| 75 | int32_t sampleDuration, |
| 76 | bool stackProfile, |
| 77 | bool useElfSymbolizer, |
| 78 | bool sendToDropbox) override; |
| Andreas Gampe | 9301b6f | 2018-04-27 15:15:34 -0700 | [diff] [blame] | 79 | Status startProfilingString(const String16& config) override; |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 80 | Status startProfilingProtobuf(const std::vector<uint8_t>& config_proto) override; |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 81 | |
| 82 | Status stopProfiling() override; |
| 83 | |
| 84 | // Override onTransact so we can handle shellCommand. |
| 85 | status_t onTransact(uint32_t _aidl_code, |
| 86 | const Parcel& _aidl_data, |
| 87 | Parcel* _aidl_reply, |
| 88 | uint32_t _aidl_flags = 0) override; |
| 89 | |
| 90 | private: |
| 91 | status_t shellCommand(int /*in*/, int out, int err, Vector<String16>& args); |
| 92 | |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 93 | template <typename ProtoLoaderFn> Status StartProfilingProtobuf(ProtoLoaderFn fn); |
| 94 | Status StartProfilingProtobufFd(int fd); |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 95 | }; |
| 96 | |
| 97 | status_t PerfProfdNativeService::start() { |
| 98 | IPCThreadState::self()->disableBackgroundScheduling(true); |
| 99 | status_t ret = BinderService<PerfProfdNativeService>::publish(); |
| 100 | if (ret != android::OK) { |
| 101 | return ret; |
| 102 | } |
| 103 | sp<ProcessState> ps(ProcessState::self()); |
| 104 | ps->startThreadPool(); |
| 105 | ps->giveThreadPoolName(); |
| 106 | return android::OK; |
| 107 | } |
| 108 | |
| 109 | status_t PerfProfdNativeService::dump(int fd, const Vector<String16> &args) { |
| 110 | auto out = std::fstream(base::StringPrintf("/proc/self/fd/%d", fd)); |
| 111 | out << "Nothing to log, yet!" << std::endl; |
| 112 | |
| 113 | return NO_ERROR; |
| 114 | } |
| 115 | |
| Andreas Gampe | 5a7181b | 2018-04-20 17:11:22 -0700 | [diff] [blame] | 116 | Status PerfProfdNativeService::startProfiling(int32_t collectionInterval, |
| 117 | int32_t iterations, |
| 118 | int32_t process, |
| 119 | int32_t samplingPeriod, |
| 120 | int32_t samplingFrequency, |
| 121 | int32_t sampleDuration, |
| 122 | bool stackProfile, |
| 123 | bool useElfSymbolizer, |
| 124 | bool sendToDropbox) { |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 125 | auto config_fn = [&](ThreadedConfig& config) { |
| 126 | config = ThreadedConfig(); // Reset to a default config. |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 127 | |
| Andreas Gampe | 5a7181b | 2018-04-20 17:11:22 -0700 | [diff] [blame] | 128 | if (collectionInterval >= 0) { |
| 129 | config.collection_interval_in_s = collectionInterval; |
| 130 | } |
| 131 | if (iterations >= 0) { |
| 132 | config.main_loop_iterations = iterations; |
| 133 | } |
| 134 | if (process >= 0) { |
| 135 | config.process = process; |
| 136 | } |
| 137 | if (samplingPeriod > 0) { |
| 138 | config.sampling_period = samplingPeriod; |
| 139 | } |
| 140 | if (samplingFrequency > 0) { |
| 141 | config.sampling_frequency = samplingFrequency; |
| 142 | } |
| 143 | if (sampleDuration > 0) { |
| 144 | config.sample_duration_in_s = sampleDuration; |
| 145 | } |
| 146 | config.stack_profile = stackProfile; |
| 147 | config.use_elf_symbolizer = useElfSymbolizer; |
| 148 | config.send_to_dropbox = sendToDropbox; |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 149 | }; |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 150 | std::string error_msg; |
| 151 | if (!StartProfiling(config_fn, &error_msg)) { |
| 152 | return Status::fromExceptionCode(1, error_msg.c_str()); |
| 153 | } |
| 154 | return Status::ok(); |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 155 | } |
| Andreas Gampe | 9301b6f | 2018-04-27 15:15:34 -0700 | [diff] [blame] | 156 | Status PerfProfdNativeService::startProfilingString(const String16& config) { |
| 157 | ConfigReader reader; |
| 158 | std::string error_msg; |
| 159 | // Split configuration along colon. |
| 160 | std::vector<std::string> args = base::Split(String8(config).string(), ":"); |
| 161 | for (auto& arg : args) { |
| 162 | if (!reader.Read(arg, /* fail_on_error */ true)) { |
| 163 | error_msg = base::StringPrintf("Could not parse %s", arg.c_str()); |
| 164 | return Status::fromExceptionCode(1, error_msg.c_str()); |
| 165 | } |
| 166 | } |
| 167 | auto config_fn = [&](ThreadedConfig& config) { |
| 168 | config = ThreadedConfig(); // Reset to a default config. |
| 169 | reader.FillConfig(&config); |
| 170 | }; |
| 171 | if (!StartProfiling(config_fn, &error_msg)) { |
| 172 | return Status::fromExceptionCode(1, error_msg.c_str()); |
| 173 | } |
| 174 | return Status::ok(); |
| 175 | } |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 176 | Status PerfProfdNativeService::startProfilingProtobuf(const std::vector<uint8_t>& config_proto) { |
| 177 | auto proto_loader_fn = [&config_proto](ProfilingConfig& proto_config) { |
| 178 | return proto_config.ParseFromArray(config_proto.data(), config_proto.size()); |
| 179 | }; |
| 180 | return StartProfilingProtobuf(proto_loader_fn); |
| 181 | } |
| 182 | |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 183 | template <typename ProtoLoaderFn> |
| 184 | Status PerfProfdNativeService::StartProfilingProtobuf(ProtoLoaderFn fn) { |
| 185 | ProfilingConfig proto_config; |
| 186 | if (!fn(proto_config)) { |
| 187 | return binder::Status::fromExceptionCode(2); |
| 188 | } |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 189 | auto config_fn = [&proto_config](ThreadedConfig& config) { |
| 190 | config = ThreadedConfig(); // Reset to a default config. |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 191 | |
| 192 | // Copy proto values. |
| 193 | #define CHECK_AND_COPY_FROM_PROTO(name) \ |
| 194 | if (proto_config.has_ ## name ()) { \ |
| 195 | config. name = proto_config. name (); \ |
| 196 | } |
| 197 | CHECK_AND_COPY_FROM_PROTO(collection_interval_in_s) |
| 198 | CHECK_AND_COPY_FROM_PROTO(use_fixed_seed) |
| 199 | CHECK_AND_COPY_FROM_PROTO(main_loop_iterations) |
| 200 | CHECK_AND_COPY_FROM_PROTO(destination_directory) |
| 201 | CHECK_AND_COPY_FROM_PROTO(config_directory) |
| 202 | CHECK_AND_COPY_FROM_PROTO(perf_path) |
| 203 | CHECK_AND_COPY_FROM_PROTO(sampling_period) |
| 204 | CHECK_AND_COPY_FROM_PROTO(sample_duration_in_s) |
| 205 | CHECK_AND_COPY_FROM_PROTO(only_debug_build) |
| 206 | CHECK_AND_COPY_FROM_PROTO(hardwire_cpus) |
| 207 | CHECK_AND_COPY_FROM_PROTO(hardwire_cpus_max_duration_in_s) |
| 208 | CHECK_AND_COPY_FROM_PROTO(max_unprocessed_profiles) |
| 209 | CHECK_AND_COPY_FROM_PROTO(stack_profile) |
| 210 | CHECK_AND_COPY_FROM_PROTO(collect_cpu_utilization) |
| 211 | CHECK_AND_COPY_FROM_PROTO(collect_charging_state) |
| 212 | CHECK_AND_COPY_FROM_PROTO(collect_booting) |
| 213 | CHECK_AND_COPY_FROM_PROTO(collect_camera_active) |
| Andreas Gampe | 9217681 | 2017-12-27 19:20:45 -0800 | [diff] [blame] | 214 | CHECK_AND_COPY_FROM_PROTO(process) |
| Andreas Gampe | 9543854 | 2018-01-09 16:18:35 -0800 | [diff] [blame] | 215 | CHECK_AND_COPY_FROM_PROTO(use_elf_symbolizer) |
| Andreas Gampe | 83476be | 2017-12-28 12:02:12 -0800 | [diff] [blame] | 216 | CHECK_AND_COPY_FROM_PROTO(send_to_dropbox) |
| Andreas Gampe | 28a379f | 2018-03-28 15:51:33 -0700 | [diff] [blame] | 217 | CHECK_AND_COPY_FROM_PROTO(compress) |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 218 | #undef CHECK_AND_COPY_FROM_PROTO |
| 219 | }; |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 220 | std::string error_msg; |
| 221 | if (!StartProfiling(config_fn, &error_msg)) { |
| 222 | return Status::fromExceptionCode(1, error_msg.c_str()); |
| 223 | } |
| 224 | return Status::ok(); |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 225 | } |
| 226 | |
| 227 | Status PerfProfdNativeService::StartProfilingProtobufFd(int fd) { |
| 228 | auto proto_loader_fn = [fd](ProfilingConfig& proto_config) { |
| 229 | struct IstreamCopyingInputStream : public google::protobuf::io::CopyingInputStream { |
| 230 | IstreamCopyingInputStream(int fd_in) |
| 231 | : stream(base::StringPrintf("/proc/self/fd/%d", fd_in), |
| 232 | std::ios::binary | std::ios::in) { |
| 233 | } |
| 234 | |
| 235 | int Read(void* buffer, int size) override { |
| 236 | stream.read(reinterpret_cast<char*>(buffer), size); |
| 237 | size_t count = stream.gcount(); |
| 238 | if (count > 0) { |
| 239 | return count; |
| 240 | } |
| 241 | return -1; |
| 242 | } |
| 243 | |
| 244 | std::ifstream stream; |
| 245 | }; |
| 246 | std::unique_ptr<IstreamCopyingInputStream> is(new IstreamCopyingInputStream(fd)); |
| 247 | std::unique_ptr<google::protobuf::io::CopyingInputStreamAdaptor> is_adaptor( |
| 248 | new google::protobuf::io::CopyingInputStreamAdaptor(is.get())); |
| 249 | return proto_config.ParseFromZeroCopyStream(is_adaptor.get()); |
| 250 | }; |
| 251 | return StartProfilingProtobuf(proto_loader_fn); |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | Status PerfProfdNativeService::stopProfiling() { |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 255 | std::string error_msg; |
| 256 | if (!StopProfiling(&error_msg)) { |
| 257 | Status::fromExceptionCode(1, error_msg.c_str()); |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 258 | } |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 259 | return Status::ok(); |
| 260 | } |
| 261 | |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 262 | status_t PerfProfdNativeService::shellCommand(int in, |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 263 | int out, |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 264 | int err_fd, |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 265 | Vector<String16>& args) { |
| 266 | if (android::base::kEnableDChecks) { |
| 267 | LOG(VERBOSE) << "Perfprofd::shellCommand"; |
| 268 | |
| 269 | for (size_t i = 0, n = args.size(); i < n; i++) { |
| 270 | LOG(VERBOSE) << " arg[" << i << "]: '" << String8(args[i]).string() << "'"; |
| 271 | } |
| 272 | } |
| 273 | |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 274 | auto err_str = std::fstream(base::StringPrintf("/proc/self/fd/%d", err_fd)); |
| 275 | |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 276 | if (args.size() >= 1) { |
| 277 | if (args[0] == String16("dump")) { |
| 278 | dump(out, args); |
| 279 | return OK; |
| 280 | } else if (args[0] == String16("startProfiling")) { |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 281 | ConfigReader reader; |
| 282 | for (size_t i = 1; i < args.size(); ++i) { |
| 283 | if (!reader.Read(String8(args[i]).string(), /* fail_on_error */ true)) { |
| 284 | err_str << base::StringPrintf("Could not parse %s", String8(args[i]).string()) |
| 285 | << std::endl; |
| 286 | return BAD_VALUE; |
| 287 | } |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 288 | } |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 289 | auto config_fn = [&](ThreadedConfig& config) { |
| 290 | config = ThreadedConfig(); // Reset to a default config. |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 291 | reader.FillConfig(&config); |
| 292 | }; |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 293 | std::string error_msg; |
| 294 | if (!StartProfiling(config_fn, &error_msg)) { |
| 295 | err_str << error_msg << std::endl; |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 296 | return UNKNOWN_ERROR; |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 297 | } |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 298 | return OK; |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 299 | } else if (args[0] == String16("startProfilingProto")) { |
| 300 | if (args.size() < 2) { |
| 301 | return BAD_VALUE; |
| 302 | } |
| 303 | int fd = -1; |
| 304 | if (args[1] == String16("-")) { |
| 305 | fd = in; |
| 306 | } else { |
| 307 | // TODO: Implement reading from disk? |
| 308 | } |
| 309 | if (fd < 0) { |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 310 | err_str << "Bad file descriptor " << args[1] << std::endl; |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 311 | return BAD_VALUE; |
| 312 | } |
| 313 | binder::Status status = StartProfilingProtobufFd(fd); |
| 314 | if (status.isOk()) { |
| 315 | return OK; |
| 316 | } else { |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 317 | err_str << status.toString8() << std::endl; |
| 318 | return UNKNOWN_ERROR; |
| Andreas Gampe | 9590c64 | 2017-12-27 10:57:34 -0800 | [diff] [blame] | 319 | } |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 320 | } else if (args[0] == String16("stopProfiling")) { |
| 321 | Status status = stopProfiling(); |
| 322 | if (status.isOk()) { |
| 323 | return OK; |
| 324 | } else { |
| Andreas Gampe | f73ddfa | 2018-03-29 14:52:57 -0700 | [diff] [blame] | 325 | err_str << status.toString8() << std::endl; |
| 326 | return UNKNOWN_ERROR; |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 327 | } |
| 328 | } |
| 329 | } |
| 330 | return BAD_VALUE; |
| 331 | } |
| 332 | |
| 333 | status_t PerfProfdNativeService::onTransact(uint32_t _aidl_code, |
| 334 | const Parcel& _aidl_data, |
| 335 | Parcel* _aidl_reply, |
| 336 | uint32_t _aidl_flags) { |
| 337 | switch (_aidl_code) { |
| 338 | case IBinder::SHELL_COMMAND_TRANSACTION: { |
| 339 | int in = _aidl_data.readFileDescriptor(); |
| 340 | int out = _aidl_data.readFileDescriptor(); |
| 341 | int err = _aidl_data.readFileDescriptor(); |
| 342 | int argc = _aidl_data.readInt32(); |
| 343 | Vector<String16> args; |
| 344 | for (int i = 0; i < argc && _aidl_data.dataAvail() > 0; i++) { |
| 345 | args.add(_aidl_data.readString16()); |
| 346 | } |
| 347 | sp<IBinder> unusedCallback; |
| 348 | sp<IResultReceiver> resultReceiver; |
| 349 | status_t status; |
| 350 | if ((status = _aidl_data.readNullableStrongBinder(&unusedCallback)) != OK) |
| 351 | return status; |
| 352 | if ((status = _aidl_data.readNullableStrongBinder(&resultReceiver)) != OK) |
| 353 | return status; |
| 354 | status = shellCommand(in, out, err, args); |
| 355 | if (resultReceiver != nullptr) { |
| 356 | resultReceiver->send(status); |
| 357 | } |
| 358 | return OK; |
| 359 | } |
| 360 | |
| 361 | default: |
| Andreas Gampe | 109780d | 2018-04-25 22:00:53 -0700 | [diff] [blame] | 362 | return ::android::os::BnPerfProfd::onTransact( |
| 363 | _aidl_code, _aidl_data, _aidl_reply, _aidl_flags); |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 364 | } |
| 365 | } |
| 366 | |
| Andreas Gampe | b019ddc | 2018-04-02 10:58:32 -0700 | [diff] [blame] | 367 | } // namespace |
| 368 | |
| Andreas Gampe | c445aff | 2017-12-27 10:44:42 -0800 | [diff] [blame] | 369 | int Main() { |
| 370 | android::status_t ret; |
| 371 | if ((ret = PerfProfdNativeService::start()) != android::OK) { |
| 372 | LOG(ERROR) << "Unable to start InstalldNativeService: %d" << ret; |
| 373 | exit(1); |
| 374 | } |
| 375 | |
| 376 | android::IPCThreadState::self()->joinThreadPool(); |
| 377 | |
| 378 | LOG(INFO) << "Exiting perfprofd"; |
| 379 | return 0; |
| 380 | } |
| 381 | |
| 382 | } // namespace binder |
| 383 | } // namespace perfprofd |
| 384 | } // namespace android |