Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 1 | /* |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 2 | * Copyright (C) 2019 The Android Open Source Project |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 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 | #define LOG_TAG "perfstatsd" |
| 18 | |
| 19 | #include <perfstatsd.h> |
| 20 | #include <perfstatsd_service.h> |
| 21 | |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 22 | enum MODE { DUMP_HISTORY, SET_OPTION }; |
| 23 | |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 24 | android::sp<Perfstatsd> perfstatsdSp; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 25 | |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 26 | void *perfstatsdMain(void *) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 27 | LOG(INFO) << "main thread started"; |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 28 | perfstatsdSp = new Perfstatsd(); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 29 | |
| 30 | while (true) { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 31 | perfstatsdSp->refresh(); |
| 32 | perfstatsdSp->pause(); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 33 | } |
| 34 | return NULL; |
| 35 | } |
| 36 | |
| 37 | void help(char **argv) { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 38 | std::string usage = argv[0]; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 39 | usage = "Usage: " + usage + " [-s][-d][-o]\n" + |
| 40 | "Options:\n" |
| 41 | " -s, start as service\n" |
| 42 | " -d, dump perf stats history for dumpstate_board\n" |
| 43 | " -o, set key/value option"; |
| 44 | |
| 45 | fprintf(stderr, "%s\n", usage.c_str()); |
| 46 | } |
| 47 | |
| 48 | int startService(void) { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 49 | pthread_t perfstatsdMainThread; |
| 50 | errno = pthread_create(&perfstatsdMainThread, NULL, perfstatsdMain, NULL); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 51 | if (errno != 0) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 52 | PLOG(ERROR) << "Failed to create main thread"; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 53 | return -1; |
| 54 | } else { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 55 | pthread_setname_np(perfstatsdMainThread, "perfstatsd_main"); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | android::ProcessState::initWithDriver("/dev/vndbinder"); |
| 59 | |
| 60 | if (PerfstatsdPrivateService::start() != android::OK) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 61 | PLOG(ERROR) << "Failed to start perfstatsd service"; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 62 | return -1; |
| 63 | } else |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 64 | LOG(INFO) << "perfstatsd_pri_service started"; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 65 | |
| 66 | android::ProcessState::self()->startThreadPool(); |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 67 | android::IPCThreadState::self()->joinThreadPool(); |
| 68 | pthread_join(perfstatsdMainThread, NULL); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 69 | return 0; |
| 70 | } |
| 71 | |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 72 | int serviceCall(int mode, const std::string &key, const std::string &value) { |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 73 | android::ProcessState::initWithDriver("/dev/vndbinder"); |
| 74 | |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 75 | android::sp<IPerfstatsdPrivate> perfstatsdPrivateService = getPerfstatsdPrivateService(); |
| 76 | if (perfstatsdPrivateService == NULL) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 77 | PLOG(ERROR) << "Cannot find perfstatsd service."; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 78 | fprintf(stdout, "Cannot find perfstatsd service.\n"); |
| 79 | return -1; |
| 80 | } |
| 81 | |
| 82 | switch (mode) { |
| 83 | case DUMP_HISTORY: { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 84 | std::string history; |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 85 | LOG(INFO) << "dump perfstats history."; |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 86 | if (!perfstatsdPrivateService->dumpHistory(&history).isOk() || history.empty()) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 87 | PLOG(ERROR) << "perf stats history is not available"; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 88 | fprintf(stdout, "perf stats history is not available\n"); |
| 89 | return -1; |
| 90 | } |
| 91 | fprintf(stdout, "%s\n", history.c_str()); |
| 92 | break; |
| 93 | } |
| 94 | case SET_OPTION: |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 95 | LOG(INFO) << "set option: " << key << " , " << value; |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 96 | if (!perfstatsdPrivateService |
| 97 | ->setOptions(std::forward<const std::string>(key), |
| 98 | std::forward<const std::string>(value)) |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 99 | .isOk()) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 100 | PLOG(ERROR) << "fail to set options"; |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 101 | fprintf(stdout, "fail to set options\n"); |
| 102 | return -1; |
| 103 | } |
| 104 | break; |
| 105 | } |
| 106 | return 0; |
| 107 | } |
| 108 | |
| 109 | int serviceCall(int mode) { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 110 | std::string empty(""); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 111 | return serviceCall(mode, empty, empty); |
| 112 | } |
| 113 | |
| 114 | int main(int argc, char **argv) { |
Tom Cherry | 4a2c84c | 2020-01-10 17:09:45 -0800 | [diff] [blame] | 115 | android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); |
| 116 | |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 117 | int c; |
| 118 | while ((c = getopt(argc, argv, "sdo:h")) != -1) { |
| 119 | switch (c) { |
| 120 | case 's': |
| 121 | return startService(); |
| 122 | case 'd': |
| 123 | return serviceCall(DUMP_HISTORY); |
| 124 | case 'o': |
| 125 | // set options |
| 126 | if (argc == 4) { |
Charles(Yen-Cheng) Chan | be3368a | 2019-01-10 16:39:54 +0800 | [diff] [blame] | 127 | std::string key(argv[2]); |
| 128 | std::string value(argv[3]); |
Charles(Yen-Cheng) Chan | 08bfed8 | 2019-01-02 12:26:16 +0800 | [diff] [blame] | 129 | return serviceCall(SET_OPTION, std::move(key), std::move(value)); |
| 130 | } |
| 131 | FALLTHROUGH_INTENDED; |
| 132 | case 'h': |
| 133 | // print usage |
| 134 | FALLTHROUGH_INTENDED; |
| 135 | default: |
| 136 | help(argv); |
| 137 | return 2; |
| 138 | } |
| 139 | } |
| 140 | return 0; |
| 141 | } |