142 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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.
 | |
|  */
 | |
| 
 | |
| #define LOG_TAG "perfstatsd"
 | |
| 
 | |
| #include <perfstatsd.h>
 | |
| #include <perfstatsd_service.h>
 | |
| 
 | |
| enum MODE { DUMP_HISTORY, SET_OPTION };
 | |
| 
 | |
| android::sp<Perfstatsd> perfstatsdSp;
 | |
| 
 | |
| void *perfstatsdMain(void *) {
 | |
|     LOG(INFO) << "main thread started";
 | |
|     perfstatsdSp = new Perfstatsd();
 | |
| 
 | |
|     while (true) {
 | |
|         perfstatsdSp->refresh();
 | |
|         perfstatsdSp->pause();
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| void help(char **argv) {
 | |
|     std::string usage = argv[0];
 | |
|     usage = "Usage: " + usage + " [-s][-d][-o]\n" +
 | |
|             "Options:\n"
 | |
|             "    -s, start as service\n"
 | |
|             "    -d, dump perf stats history for dumpstate_board\n"
 | |
|             "    -o, set key/value option";
 | |
| 
 | |
|     fprintf(stderr, "%s\n", usage.c_str());
 | |
| }
 | |
| 
 | |
| int startService(void) {
 | |
|     pthread_t perfstatsdMainThread;
 | |
|     errno = pthread_create(&perfstatsdMainThread, NULL, perfstatsdMain, NULL);
 | |
|     if (errno != 0) {
 | |
|         PLOG(ERROR) << "Failed to create main thread";
 | |
|         return -1;
 | |
|     } else {
 | |
|         pthread_setname_np(perfstatsdMainThread, "perfstatsd_main");
 | |
|     }
 | |
| 
 | |
|     android::ProcessState::initWithDriver("/dev/vndbinder");
 | |
| 
 | |
|     if (PerfstatsdPrivateService::start() != android::OK) {
 | |
|         PLOG(ERROR) << "Failed to start perfstatsd service";
 | |
|         return -1;
 | |
|     } else
 | |
|         LOG(INFO) << "perfstatsd_pri_service started";
 | |
| 
 | |
|     android::ProcessState::self()->startThreadPool();
 | |
|     android::IPCThreadState::self()->joinThreadPool();
 | |
|     pthread_join(perfstatsdMainThread, NULL);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int serviceCall(int mode, const std::string &key, const std::string &value) {
 | |
|     android::ProcessState::initWithDriver("/dev/vndbinder");
 | |
| 
 | |
|     android::sp<IPerfstatsdPrivate> perfstatsdPrivateService = getPerfstatsdPrivateService();
 | |
|     if (perfstatsdPrivateService == NULL) {
 | |
|         PLOG(ERROR) << "Cannot find perfstatsd service.";
 | |
|         fprintf(stdout, "Cannot find perfstatsd service.\n");
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     switch (mode) {
 | |
|         case DUMP_HISTORY: {
 | |
|             std::string history;
 | |
|             LOG(INFO) << "dump perfstats history.";
 | |
|             if (!perfstatsdPrivateService->dumpHistory(&history).isOk() || history.empty()) {
 | |
|                 PLOG(ERROR) << "perf stats history is not available";
 | |
|                 fprintf(stdout, "perf stats history is not available\n");
 | |
|                 return -1;
 | |
|             }
 | |
|             fprintf(stdout, "%s\n", history.c_str());
 | |
|             break;
 | |
|         }
 | |
|         case SET_OPTION:
 | |
|             LOG(INFO) << "set option: " << key << " , " << value;
 | |
|             if (!perfstatsdPrivateService
 | |
|                      ->setOptions(std::forward<const std::string>(key),
 | |
|                                   std::forward<const std::string>(value))
 | |
|                      .isOk()) {
 | |
|                 PLOG(ERROR) << "fail to set options";
 | |
|                 fprintf(stdout, "fail to set options\n");
 | |
|                 return -1;
 | |
|             }
 | |
|             break;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int serviceCall(int mode) {
 | |
|     std::string empty("");
 | |
|     return serviceCall(mode, empty, empty);
 | |
| }
 | |
| 
 | |
| int main(int argc, char **argv) {
 | |
|     android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
 | |
| 
 | |
|     int c;
 | |
|     while ((c = getopt(argc, argv, "sdo:h")) != -1) {
 | |
|         switch (c) {
 | |
|             case 's':
 | |
|                 return startService();
 | |
|             case 'd':
 | |
|                 return serviceCall(DUMP_HISTORY);
 | |
|             case 'o':
 | |
|                 // set options
 | |
|                 if (argc == 4) {
 | |
|                     std::string key(argv[2]);
 | |
|                     std::string value(argv[3]);
 | |
|                     return serviceCall(SET_OPTION, std::move(key), std::move(value));
 | |
|                 }
 | |
|                 FALLTHROUGH_INTENDED;
 | |
|             case 'h':
 | |
|                 // print usage
 | |
|                 FALLTHROUGH_INTENDED;
 | |
|             default:
 | |
|                 help(argv);
 | |
|                 return 2;
 | |
|         }
 | |
|     }
 | |
|     return 0;
 | |
| }
 |