17e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh/* 27e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** 37e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** Copyright 2015, The Android Open Source Project 47e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** 57e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** Licensed under the Apache License, Version 2.0 (the "License"); 67e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** you may not use this file except in compliance with the License. 77e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** You may obtain a copy of the License at 87e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** 97e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** http://www.apache.org/licenses/LICENSE-2.0 107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** 117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** Unless required by applicable law or agreed to in writing, software 127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** distributed under the License is distributed on an "AS IS" BASIS, 137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** See the License for the specific language governing permissions and 157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh** limitations under the License. 167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh*/ 177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <assert.h> 197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <dirent.h> 207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <errno.h> 217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <fcntl.h> 227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <signal.h> 237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <stdio.h> 247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <stdlib.h> 257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <string.h> 267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <sys/stat.h> 277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <sys/types.h> 2807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh#include <sys/wait.h> 297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <time.h> 307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <unistd.h> 317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <string> 3207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh#include <sstream> 337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <map> 34f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen#include <set> 357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cctype> 367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 3766dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/file.h> 3866dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/stringprintf.h> 397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cutils/properties.h> 407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perfprofdcore.h" 427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perfprofdutils.h" 437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perf_data_converter.h" 4407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh#include "cpuconfig.h" 458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh#include "configreader.h" 467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Perf profiling daemon -- collects system-wide profiles using 497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 5007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh// simpleperf record -a 517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// and encodes them so that they can be uploaded by a separate service. 537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh//...................................................................... 567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 5807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh// Output file from 'perf record'. 597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#define PERF_OUTPUT "perf.data" 617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// This enum holds the results of the "should we profile" configuration check. 647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshtypedef enum { 667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // All systems go for profile collection. 687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh DO_COLLECT_PROFILE, 697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 7058bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen // The selected configuration directory doesn't exist. 7158bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen DONT_PROFILE_MISSING_CONFIG_DIR, 727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Destination directory does not contain the semaphore file that 747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // the perf profile uploading service creates when it determines 757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // that the user has opted "in" for usage data collection. No 767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // semaphore -> no user approval -> no profiling. 777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh DONT_PROFILE_MISSING_SEMAPHORE, 787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // No perf executable present 807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh DONT_PROFILE_MISSING_PERF_EXECUTABLE, 817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // We're running in the emulator, perf won't be able to do much 837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh DONT_PROFILE_RUNNING_IN_EMULATOR 847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} CKPROFILE_RESULT; 867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Are we running in the emulator? If so, stub out profile collection 897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Starts as uninitialized (-1), then set to 1 or 0 at init time. 907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic int running_in_emulator = -1; 927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Is this a debug build ('userdebug' or 'eng')? 957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Starts as uninitialized (-1), then set to 1 or 0 at init time. 967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic int is_debug_build = -1; 987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 100a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// Path to the perf file to convert and exit? Empty value is the default, daemon mode. 101a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// 102a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrovstatic std::string perf_file_to_convert = ""; 103a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov 104a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// 1057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Random number generator seed (set at startup time). 1067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic unsigned short random_seed[3]; 1087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 1097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1108c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// SIGHUP handler. Sending SIGHUP to the daemon can be used to break it 1118c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// out of a sleep() call so as to trigger a new collection (debugging) 1127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1138c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshstatic void sig_hup(int /* signum */) 1147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 1158c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGW("SIGHUP received"); 1167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 1177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 1187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 119a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// Parse command line args. Currently supported flags: 120a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// * "-c PATH" sets the path of the config file to PATH. 121a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// * "-x PATH" reads PATH as a perf data file and saves it as a file in 122a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// perf_profile.proto format. ".encoded" suffix is appended to PATH to form 123a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov// the output file path. 1247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic void parse_args(int argc, char** argv) 1267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 1277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh int ac; 1287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 1297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh for (ac = 1; ac < argc; ++ac) { 1307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (!strcmp(argv[ac], "-c")) { 1317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (ac >= argc-1) { 1327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGE("malformed command line: -c option requires argument)"); 1337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh continue; 1347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 1358c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh ConfigReader::setConfigFilePath(argv[ac+1]); 1367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh ++ac; 137a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov } else if (!strcmp(argv[ac], "-x")) { 138a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov if (ac >= argc-1) { 139a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov W_ALOGE("malformed command line: -x option requires argument)"); 140a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov continue; 141a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov } 142a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov perf_file_to_convert = argv[ac+1]; 143a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov ++ac; 1447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } else { 1457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGE("malformed command line: unknown option or arg %s)", argv[ac]); 1467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh continue; 1477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 1487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 1497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 1507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 1517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Convert a CKPROFILE_RESULT to a string 1537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst char *ckprofile_result_to_string(CKPROFILE_RESULT result) 1557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 15607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh switch (result) { 1577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case DO_COLLECT_PROFILE: 1587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "DO_COLLECT_PROFILE"; 15958bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen case DONT_PROFILE_MISSING_CONFIG_DIR: 16058bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen return "missing config directory"; 1617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case DONT_PROFILE_MISSING_SEMAPHORE: 1627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "missing semaphore file"; 1637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case DONT_PROFILE_MISSING_PERF_EXECUTABLE: 1647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "missing 'perf' executable"; 1657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case DONT_PROFILE_RUNNING_IN_EMULATOR: 1667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "running in emulator"; 1677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh default: return "unknown"; 1687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 1697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "notreached"; 1707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 1717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 1727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Convert a PROFILE_RESULT to a string 1747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst char *profile_result_to_string(PROFILE_RESULT result) 1767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 1777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh switch(result) { 1787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case OK_PROFILE_COLLECTION: 1797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "profile collection succeeded"; 1807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case ERR_FORK_FAILED: 1817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "fork() system call failed"; 1827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case ERR_PERF_RECORD_FAILED: 1837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "perf record returned bad exit status"; 1847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case ERR_PERF_ENCODE_FAILED: 1857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "failure encoding perf.data to protobuf"; 1867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case ERR_OPEN_ENCODED_FILE_FAILED: 1877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "failed to open encoded perf file"; 1887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh case ERR_WRITE_ENCODED_FILE_FAILED: 1897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "write to encoded perf file failed"; 1907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh default: return "unknown"; 1917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 1927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return "notreached"; 1937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 1947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 1957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Check to see whether we should perform a profile collection 1977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic CKPROFILE_RESULT check_profiling_enabled(ConfigReader &config) 1997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 2007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 2017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Profile collection in the emulator doesn't make sense 2027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 2037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh assert(running_in_emulator != -1); 2047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (running_in_emulator) { 2057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return DONT_PROFILE_RUNNING_IN_EMULATOR; 2067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 2077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 2087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 20958bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen // Check for existence of semaphore file in config directory 2107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 21158bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen if (access(config.getStringValue("config_directory").c_str(), F_OK) == -1) { 21258bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen W_ALOGW("unable to open config directory %s: (%s)", 21358bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen config.getStringValue("config_directory").c_str(), strerror(errno)); 21458bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen return DONT_PROFILE_MISSING_CONFIG_DIR; 2157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 2167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 21758bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen 21858bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen // Check for existence of semaphore file 21958bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen std::string semaphore_filepath = config.getStringValue("config_directory") 22058bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen + "/" + SEMAPHORE_FILENAME; 22158bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen if (access(semaphore_filepath.c_str(), F_OK) == -1) { 22258bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen return DONT_PROFILE_MISSING_SEMAPHORE; 22358bade36c738ed96137cfcc8d15f0505f085b5aeDehao Chen } 2247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 22507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // Check for existence of simpleperf/perf executable 2267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh std::string pp = config.getStringValue("perf_path"); 2277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (access(pp.c_str(), R_OK|X_OK) == -1) { 2287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGW("unable to access/execute %s", pp.c_str()); 2297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return DONT_PROFILE_MISSING_PERF_EXECUTABLE; 2307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 2317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 2327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 2337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // We are good to go 2347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 2357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return DO_COLLECT_PROFILE; 2367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 2377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 2388c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshbool get_booting() 239ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh{ 2408c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh char propBuf[PROPERTY_VALUE_MAX]; 2418c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh propBuf[0] = '\0'; 2428c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh property_get("sys.boot_completed", propBuf, ""); 2438c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return (propBuf[0] != '1'); 2448c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh} 2458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 2468c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// 2478c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// Constructor takes a timeout (in seconds) and a child pid; If an 2488c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// alarm set for the specified number of seconds triggers, then a 2498c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// SIGKILL is sent to the child. Destructor resets alarm. Example: 2508c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// 2518c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// pid_t child_pid = ...; 2528c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// { AlarmHelper h(10, child_pid); 2538c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// ... = read_from_child(child_pid, ...); 2548c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// } 2558c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// 2568c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// NB: this helper is not re-entrant-- avoid nested use or 2578c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// use by multiple threads 2588c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// 2598c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshclass AlarmHelper { 2608c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh public: 2618c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh AlarmHelper(unsigned num_seconds, pid_t child) 2628c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh { 2638c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh struct sigaction sigact; 2648c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh assert(child); 2658c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh assert(child_ == 0); 2668c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh memset(&sigact, 0, sizeof(sigact)); 2678c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh sigact.sa_sigaction = handler; 2688c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh sigaction(SIGALRM, &sigact, &oldsigact_); 2698c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh child_ = child; 2708c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh alarm(num_seconds); 2718c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 2728c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh ~AlarmHelper() 2738c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh { 2748c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh alarm(0); 2758c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh child_ = 0; 2768c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh sigaction(SIGALRM, &oldsigact_, NULL); 2778c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 2788c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh static void handler(int, siginfo_t *, void *); 2798c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 2808c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh private: 2818c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh struct sigaction oldsigact_; 2828c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh static pid_t child_; 2838c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh}; 2848c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 2858c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshpid_t AlarmHelper::child_; 2868c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 2878c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshvoid AlarmHelper::handler(int, siginfo_t *, void *) 2888c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{ 2898c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGW("SIGALRM timeout"); 2908c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh kill(child_, SIGKILL); 2918c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh} 2928c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 2938c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// 2948c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// This implementation invokes "dumpsys media.camera" and inspects the 2958c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// output to determine if any camera clients are active. NB: this is 2968c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// currently disable (via config option) until the selinux issues can 2978c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// be sorted out. Another possible implementation (not yet attempted) 2988c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// would be to use the binder to call into the native camera service 2998c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// via "ICameraService". 3008c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh// 3018c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshbool get_camera_active() 3028c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{ 3038c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh int pipefds[2]; 3048c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (pipe2(pipefds, O_CLOEXEC) != 0) { 3058c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGE("pipe2() failed (%s)", strerror(errno)); 3068c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return false; 3078c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3088c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh pid_t pid = fork(); 3098c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (pid == -1) { 3108c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGE("fork() failed (%s)", strerror(errno)); 3118c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh close(pipefds[0]); 3128c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh close(pipefds[1]); 3138c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return false; 3148c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } else if (pid == 0) { 3158c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // child 3168c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh close(pipefds[0]); 3178c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh dup2(pipefds[1], fileno(stderr)); 3188c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh dup2(pipefds[1], fileno(stdout)); 3198c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh const char *argv[10]; 3208c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh unsigned slot = 0; 3218c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh argv[slot++] = "/system/bin/dumpsys"; 3228c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh argv[slot++] = "media.camera"; 3238c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh argv[slot++] = nullptr; 3248c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh execvp(argv[0], (char * const *)argv); 3258c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGE("execvp() failed (%s)", strerror(errno)); 3268c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return false; 3278c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3288c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // parent 3298c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh AlarmHelper helper(10, pid); 3308c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh close(pipefds[1]); 3318c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 3328c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // read output 3338c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh bool have_cam = false; 3348c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh bool have_clients = true; 3358c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string dump_output; 3368c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh bool result = android::base::ReadFdToString(pipefds[0], &dump_output); 3378c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh close(pipefds[0]); 3388c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (result) { 3398c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::stringstream ss(dump_output); 3408c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string line; 3418c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh while (std::getline(ss,line,'\n')) { 3428c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (line.find("Camera module API version:") != 3438c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string::npos) { 3448c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh have_cam = true; 3458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3468c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (line.find("No camera module available") != 3478c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string::npos || 3488c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh line.find("No active camera clients yet") != 3498c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string::npos) { 3508c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh have_clients = false; 3518c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3528c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3538c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3548c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 3558c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // reap child (no zombies please) 3568c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh int st = 0; 3578c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh TEMP_FAILURE_RETRY(waitpid(pid, &st, 0)); 3588c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return have_cam && have_clients; 3598c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh} 3608c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 3618c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshbool get_charging() 3628c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{ 3638c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string psdir("/sys/class/power_supply"); 3648c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh DIR* dir = opendir(psdir.c_str()); 3658c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (dir == NULL) { 3668c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGE("Failed to open dir %s (%s)", psdir.c_str(), strerror(errno)); 3678c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return false; 3688c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3698c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh struct dirent* e; 3708c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh bool result = false; 3718c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh while ((e = readdir(dir)) != 0) { 3728c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (e->d_name[0] != '.') { 3738c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string online_path = psdir + "/" + e->d_name + "/online"; 3748c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string contents; 3758c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh int value = 0; 3768c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (android::base::ReadFileToString(online_path.c_str(), &contents) && 3778c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh sscanf(contents.c_str(), "%d", &value) == 1) { 3788c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (value) { 3798c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh result = true; 3808c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh break; 3818c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3828c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3838c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3848c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 3858c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh closedir(dir); 3868c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return result; 3878c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh} 3888c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 3898c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshbool postprocess_proc_stat_contents(const std::string &pscontents, 3908c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned *idleticks, 3918c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned *remainingticks) 3928c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{ 3938c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned usertime, nicetime, systime, idletime, iowaittime; 3948c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned irqtime, softirqtime; 3958c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 3968c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh int rc = sscanf(pscontents.c_str(), "cpu %lu %lu %lu %lu %lu %lu %lu", 3978c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh &usertime, &nicetime, &systime, &idletime, 3988c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh &iowaittime, &irqtime, &softirqtime); 3998c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (rc != 7) { 4008c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return false; 4018c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4028c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh *idleticks = idletime; 4038c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh *remainingticks = usertime + nicetime + systime + iowaittime + irqtime + softirqtime; 4048c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return true; 4058c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh} 4068c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 4078c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshunsigned collect_cpu_utilization() 4088c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{ 4098c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh std::string contents; 4108c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned idle[2]; 4118c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned busy[2]; 4128c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh for (unsigned iter = 0; iter < 2; ++iter) { 4138c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (!android::base::ReadFileToString("/proc/stat", &contents)) { 4148c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return 0; 4158c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4168c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (!postprocess_proc_stat_contents(contents, &idle[iter], &busy[iter])) { 4178c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return 0; 4188c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4198c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (iter == 0) { 4208c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh sleep(1); 4218c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4228c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4238c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned total_delta = (idle[1] + busy[1]) - (idle[0] + busy[0]); 4248c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh long unsigned busy_delta = busy[1] - busy[0]; 4258c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return busy_delta * 100 / total_delta; 4268c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh} 4278c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 4288c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntoshstatic void annotate_encoded_perf_profile(wireless_android_play_playlog::AndroidPerfProfile *profile, 4298c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh const ConfigReader &config, 4308c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh unsigned cpu_utilization) 4318c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh{ 4328c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // 4338c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // Incorporate cpu utilization (collected prior to perf run) 4348c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // 4358c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (config.getUnsignedValue("collect_cpu_utilization")) { 4368c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh profile->set_cpu_utilization(cpu_utilization); 4378c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4388c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 439ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // 440ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // Load average as reported by the kernel 441ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // 442ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh std::string load; 443ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh double fload = 0.0; 444ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh if (android::base::ReadFileToString("/proc/loadavg", &load) && 445ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh sscanf(load.c_str(), "%lf", &fload) == 1) { 446ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh int iload = static_cast<int>(fload * 100.0); 447ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh profile->set_sys_load_average(iload); 448ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh } else { 449ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh W_ALOGE("Failed to read or scan /proc/loadavg (%s)", strerror(errno)); 450ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh } 451ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh 452ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // 4538c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // Device still booting? Camera in use? Plugged into charger? 4548c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // 4558c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh bool is_booting = get_booting(); 4568c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (config.getUnsignedValue("collect_booting")) { 4578c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh profile->set_booting(is_booting); 4588c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4598c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (config.getUnsignedValue("collect_camera_active")) { 4608c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh profile->set_camera_active(is_booting ? false : get_camera_active()); 4618c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4628c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (config.getUnsignedValue("collect_charging_state")) { 4638c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh profile->set_on_charger(get_charging()); 4648c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 4658c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 4668c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // 467ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // Examine the contents of wake_unlock to determine whether the 468ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // device display is on or off. NB: is this really the only way to 469ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // determine this info? 470ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // 471ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh std::string disp; 472ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh if (android::base::ReadFileToString("/sys/power/wake_unlock", &disp)) { 473ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh bool ison = (strstr(disp.c_str(), "PowerManagerService.Display") == 0); 474ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh profile->set_display_on(ison); 475ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh } else { 476ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh W_ALOGE("Failed to read /sys/power/wake_unlock (%s)", strerror(errno)); 477ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh } 478ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh} 479ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh 4807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshinline char* string_as_array(std::string* str) { 4817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return str->empty() ? NULL : &*str->begin(); 4827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 4837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 4847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshPROFILE_RESULT encode_to_proto(const std::string &data_file_path, 4858c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh const char *encoded_file_path, 4868c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh const ConfigReader &config, 4878c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh unsigned cpu_utilization) 4887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 4897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 4907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Open and read perf.data file 4917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 4927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh const wireless_android_play_playlog::AndroidPerfProfile &encodedProfile = 4937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh wireless_android_logging_awp::RawPerfDataToAndroidPerfProfile(data_file_path); 4947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 4957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 4967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Issue error if no samples 4977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 4987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (encodedProfile.programs().size() == 0) { 4997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return ERR_PERF_ENCODE_FAILED; 5007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 5017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 502ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh // All of the info in 'encodedProfile' is derived from the perf.data file; 5038c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // here we tack display status, cpu utilization, system load, etc. 504ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh wireless_android_play_playlog::AndroidPerfProfile &prof = 505ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh const_cast<wireless_android_play_playlog::AndroidPerfProfile&> 506ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh (encodedProfile); 5078c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh annotate_encoded_perf_profile(&prof, config, cpu_utilization); 508ebb946827ffbbb7df4c41be262a627c02bd95888Than McIntosh 5097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 5107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Serialize protobuf to array 5117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 5127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh int size = encodedProfile.ByteSize(); 5137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh std::string data; 5147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh data.resize(size); 5157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh ::google::protobuf::uint8* dtarget = 5167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh reinterpret_cast<::google::protobuf::uint8*>(string_as_array(&data)); 5177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh encodedProfile.SerializeWithCachedSizesToArray(dtarget); 5187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 5197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 5207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Open file and write encoded data to it 5217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 522f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen FILE *fp = fopen(encoded_file_path, "w"); 5237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (!fp) { 5247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return ERR_OPEN_ENCODED_FILE_FAILED; 5257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 5267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh size_t fsiz = size; 5277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (fwrite(dtarget, fsiz, 1, fp) != 1) { 5287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh fclose(fp); 5297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return ERR_WRITE_ENCODED_FILE_FAILED; 5307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 5317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh fclose(fp); 532f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen chmod(encoded_file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); 5337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 5347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return OK_PROFILE_COLLECTION; 5357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 5367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 5377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 53807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh// Invoke "perf record". Return value is OK_PROFILE_COLLECTION for 53907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh// success, or some other error code if something went wrong. 54007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh// 54107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntoshstatic PROFILE_RESULT invoke_perf(const std::string &perf_path, 54207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh unsigned sampling_period, 54307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh const char *stack_profile_opt, 54407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh unsigned duration, 54507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh const std::string &data_file_path, 54607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh const std::string &perf_stderr_path) 54707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh{ 54807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh pid_t pid = fork(); 54907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 55007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh if (pid == -1) { 55107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh return ERR_FORK_FAILED; 55207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } 55307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 55407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh if (pid == 0) { 55507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // child 55607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 55707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // Open file to receive stderr/stdout from perf 55807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh FILE *efp = fopen(perf_stderr_path.c_str(), "w"); 55907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh if (efp) { 56007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh dup2(fileno(efp), STDERR_FILENO); 56107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh dup2(fileno(efp), STDOUT_FILENO); 56207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } else { 56307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh W_ALOGW("unable to open %s for writing", perf_stderr_path.c_str()); 56407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } 56507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 56607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // marshall arguments 567e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh constexpr unsigned max_args = 13; 56807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh const char *argv[max_args]; 56907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh unsigned slot = 0; 57007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = perf_path.c_str(); 57107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = "record"; 57207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 57307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // -o perf.data 57407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = "-o"; 57507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = data_file_path.c_str(); 57607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 57707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // -c N 57807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = "-c"; 579f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string p_str = android::base::StringPrintf("%u", sampling_period); 580f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen argv[slot++] = p_str.c_str(); 58107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 58207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // -g if desired 58307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh if (stack_profile_opt) 58407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = stack_profile_opt; 58507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 58607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // system wide profiling 58707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = "-a"; 58807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 589e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh // no need for kernel symbols 590e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh argv[slot++] = "--no-dump-kernel-symbols"; 591e42c1f126a76b4ed4f95ef8fcdfea6866002c185Than McIntosh 59207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // sleep <duration> 59307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = "/system/bin/sleep"; 594f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string d_str = android::base::StringPrintf("%u", duration); 595f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen argv[slot++] = d_str.c_str(); 59607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 59707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // terminator 59807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh argv[slot++] = nullptr; 59907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh assert(slot < max_args); 60007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 60107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // record the final command line in the error output file for 60207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // posterity/debugging purposes 60307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh fprintf(stderr, "perf invocation (pid=%d):\n", getpid()); 60407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh for (unsigned i = 0; argv[i] != nullptr; ++i) { 60507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh fprintf(stderr, "%s%s", i ? " " : "", argv[i]); 60607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } 60707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh fprintf(stderr, "\n"); 60807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 60907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // exec 61007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh execvp(argv[0], (char * const *)argv); 61107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh fprintf(stderr, "exec failed: %s\n", strerror(errno)); 61207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh exit(1); 61307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 61407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } else { 61507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // parent 61607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh int st = 0; 61707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh pid_t reaped = TEMP_FAILURE_RETRY(waitpid(pid, &st, 0)); 61807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 61907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh if (reaped == -1) { 62007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh W_ALOGW("waitpid failed: %s", strerror(errno)); 62107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } else if (WIFSIGNALED(st)) { 62207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh W_ALOGW("perf killed by signal %d", WTERMSIG(st)); 62307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } else if (WEXITSTATUS(st) != 0) { 62407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh W_ALOGW("perf bad exit status %d", WEXITSTATUS(st)); 62507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } else { 62607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh return OK_PROFILE_COLLECTION; 62707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } 62807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh } 62907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 63007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh return ERR_PERF_RECORD_FAILED; 63107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh} 63207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 63307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh// 634f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// Remove all files in the destination directory during initialization 635f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// 636f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chenstatic void cleanup_destination_dir(const ConfigReader &config) 637f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen{ 638f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string dest_dir = config.getStringValue("destination_directory"); 639f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen DIR* dir = opendir(dest_dir.c_str()); 640f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (dir != NULL) { 641f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen struct dirent* e; 642f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen while ((e = readdir(dir)) != 0) { 643f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (e->d_name[0] != '.') { 644f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string file_path = dest_dir + "/" + e->d_name; 645f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen remove(file_path.c_str()); 646f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 647f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 648f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen closedir(dir); 649f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh } else { 650f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh W_ALOGW("unable to open destination dir %s for cleanup", 651f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh dest_dir.c_str()); 652f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 653f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen} 654f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 655f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// 656f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// Post-processes after profile is collected and converted to protobuf. 657f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// * GMS core stores processed file sequence numbers in 658f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// /data/data/com.google.android.gms/files/perfprofd_processed.txt 659f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// * Update /data/misc/perfprofd/perfprofd_produced.txt to remove the sequence 660f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// numbers that have been processed and append the current seq number 661f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// Returns true if the current_seq should increment. 662f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// 663f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chenstatic bool post_process(const ConfigReader &config, int current_seq) 664f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen{ 665f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string dest_dir = config.getStringValue("destination_directory"); 666f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string processed_file_path = 667f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen config.getStringValue("config_directory") + "/" + PROCESSED_FILENAME; 668f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string produced_file_path = dest_dir + "/" + PRODUCED_FILENAME; 669f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 670f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 671f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::set<int> processed; 672f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen FILE *fp = fopen(processed_file_path.c_str(), "r"); 673f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (fp != NULL) { 674f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen int seq; 675f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen while(fscanf(fp, "%d\n", &seq) > 0) { 676f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (remove(android::base::StringPrintf( 677f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen "%s/perf.data.encoded.%d", dest_dir.c_str(),seq).c_str()) == 0) { 678f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen processed.insert(seq); 679f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 680f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 681f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen fclose(fp); 682f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 683f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 684f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::set<int> produced; 685f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen fp = fopen(produced_file_path.c_str(), "r"); 686f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (fp != NULL) { 687f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen int seq; 688f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen while(fscanf(fp, "%d\n", &seq) > 0) { 689f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (processed.find(seq) == processed.end()) { 690f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen produced.insert(seq); 691f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 692f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 693f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen fclose(fp); 694f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 695f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 696f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh unsigned maxLive = config.getUnsignedValue("max_unprocessed_profiles"); 697f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh if (produced.size() >= maxLive) { 698f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen return false; 699f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 700f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 701f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen produced.insert(current_seq); 702f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen fp = fopen(produced_file_path.c_str(), "w"); 703f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (fp == NULL) { 704f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen W_ALOGW("Cannot write %s", produced_file_path.c_str()); 705f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen return false; 706f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 707f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen for (std::set<int>::const_iterator iter = produced.begin(); 708f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen iter != produced.end(); ++iter) { 709f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen fprintf(fp, "%d\n", *iter); 710f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 711f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen fclose(fp); 712f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen chmod(produced_file_path.c_str(), 713f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); 714f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen return true; 715f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen} 716f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen 717f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen// 7187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Collect a perf profile. Steps for this operation are: 7197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// - kick off 'perf record' 7207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// - read perf.data, convert to protocol buf 7217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 722f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chenstatic PROFILE_RESULT collect_profile(const ConfigReader &config, int seq) 7237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 7247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 7258c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // Collect cpu utilization if enabled 7268c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // 7278c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh unsigned cpu_utilization = 0; 7288c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (config.getUnsignedValue("collect_cpu_utilization")) { 7298c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh cpu_utilization = collect_cpu_utilization(); 7308c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 7318c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 7328c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh // 7337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Form perf.data file name, perf error output file name 7347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 7357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh std::string destdir = config.getStringValue("destination_directory"); 7367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh std::string data_file_path(destdir); 7377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh data_file_path += "/"; 7387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh data_file_path += PERF_OUTPUT; 7397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh std::string perf_stderr_path(destdir); 7407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh perf_stderr_path += "/perferr.txt"; 7417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 7427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 7437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Remove any existing perf.data file -- if we don't do this, perf 7447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // will rename the old file and we'll have extra cruft lying around. 7457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 7467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh struct stat statb; 7477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (stat(data_file_path.c_str(), &statb) == 0) { // if file exists... 7487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (unlink(data_file_path.c_str())) { // then try to remove 7497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGW("unable to unlink previous perf.data file"); 7507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 7517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 7527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 7537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 75407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // The "mpdecision" daemon can cause problems for profile 75507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // collection: if it decides to online a CPU partway through the 75607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // 'perf record' run, the activity on that CPU will be invisible to 75707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // perf, and if it offlines a CPU during the recording this can 75807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // sometimes leave the PMU in an unusable state (dmesg errors of the 75907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // form "perfevents: unable to request IRQXXX for ..."). To avoid 76007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // these issues, if "mpdecision" is running the helper below will 76107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // stop the service and then online all available CPUs. The object 76207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // destructor (invoked when this routine terminates) will then 76307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // restart the service again when needed. 7647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 7657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned duration = config.getUnsignedValue("sample_duration"); 76607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh unsigned hardwire = config.getUnsignedValue("hardwire_cpus"); 76707f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh unsigned max_duration = config.getUnsignedValue("hardwire_cpus_max_duration"); 76807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh bool take_action = (hardwire && duration <= max_duration); 76907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh HardwireCpuHelper helper(take_action); 77007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 77107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // 77207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // Invoke perf 77307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // 77407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh const char *stack_profile_opt = 77507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh (config.getUnsignedValue("stack_profile") != 0 ? "-g" : nullptr); 77607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh std::string perf_path = config.getStringValue("perf_path"); 7777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned period = config.getUnsignedValue("sampling_period"); 77807f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh 77907f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh PROFILE_RESULT ret = invoke_perf(perf_path.c_str(), 78007f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh period, 78107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh stack_profile_opt, 78207f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh duration, 78307f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh data_file_path, 78407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh perf_stderr_path); 78507f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh if (ret != OK_PROFILE_COLLECTION) { 78607f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh return ret; 7877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 7887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 7897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 7907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Read the resulting perf.data file, encode into protocol buffer, then write 79107f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh // the result to the file perf.data.encoded 7927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 793f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen std::string path = android::base::StringPrintf( 794f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen "%s.encoded.%d", data_file_path.c_str(), seq); 7958c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh return encode_to_proto(data_file_path, path.c_str(), config, cpu_utilization); 7967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 7977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 7987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 7997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Assuming that we want to collect a profile every N seconds, 8007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// randomly partition N into two sub-intervals. 8017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic void determine_before_after(unsigned &sleep_before_collect, 8037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned &sleep_after_collect, 8047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned collection_interval) 8057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 8067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh double frac = erand48(random_seed); 8077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh sleep_before_collect = (unsigned) (((double)collection_interval) * frac); 8087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh assert(sleep_before_collect <= collection_interval); 8097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh sleep_after_collect = collection_interval - sleep_before_collect; 8107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 8117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Set random number generator seed 8147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic void set_seed(ConfigReader &config) 8167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 8177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned seed = 0; 8187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned use_fixed_seed = config.getUnsignedValue("use_fixed_seed"); 8197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (use_fixed_seed) { 8207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 8217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Use fixed user-specified seed 8227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 8237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh seed = use_fixed_seed; 8247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } else { 8257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 8267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Randomized seed 8277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // 8287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh seed = arc4random(); 8297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 8307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("random seed set to %u", seed); 8317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Distribute the 32-bit seed into the three 16-bit array 8327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // elements. The specific values being written do not especially 8337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // matter as long as we are setting them to something based on the seed. 8347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh random_seed[0] = seed & 0xffff; 8357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh random_seed[1] = (seed >> 16); 8367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh random_seed[2] = (random_seed[0] ^ random_seed[1]); 8377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 8387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Initialization 8417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstatic void init(ConfigReader &config) 8437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 8448c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh if (!config.readFile()) { 8458c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh W_ALOGE("unable to open configuration file %s", 8468c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh config.getConfigFilePath()); 8478c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh } 8488c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh 849fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh // Children of init inherit an artificially low OOM score -- this is not 850fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh // desirable for perfprofd (its OOM score should be on par with 851fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh // other user processes). 852fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh std::stringstream oomscore_path; 853fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh oomscore_path << "/proc/" << getpid() << "/oom_score_adj"; 854fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh if (!android::base::WriteStringToFile("0", oomscore_path.str())) { 855fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh W_ALOGE("unable to write to %s", oomscore_path.str().c_str()); 856fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh } 857fd6bb2d486084a0eeeb11767b17234cf4a23159dThan McIntosh 8587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh set_seed(config); 859f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen cleanup_destination_dir(config); 8607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh char propBuf[PROPERTY_VALUE_MAX]; 8627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh propBuf[0] = '\0'; 8637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh property_get("ro.kernel.qemu", propBuf, ""); 8647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh running_in_emulator = (propBuf[0] == '1'); 8657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh property_get("ro.debuggable", propBuf, ""); 8667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh is_debug_build = (propBuf[0] == '1'); 8677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh signal(SIGHUP, sig_hup); 8697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 8707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Main routine: 8737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 1. parse cmd line args 8747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 2. read config file 8757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 3. loop: { 8767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// sleep for a while 8777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// perform a profile collection 8787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// } 8797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// 8807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshint perfprofd_main(int argc, char** argv) 8817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{ 8827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh ConfigReader config; 8837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("starting Android Wide Profiling daemon"); 8857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 8867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh parse_args(argc, argv); 8877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh init(config); 8887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 889a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov if (!perf_file_to_convert.empty()) { 890a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov std::string encoded_path = perf_file_to_convert + ".encoded"; 891a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov encode_to_proto(perf_file_to_convert, encoded_path.c_str(), config, 0); 892a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov return 0; 893a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov } 894a5cbb7a0538bd63d87f11be13ce1d85bb594e20dAlexey Alexandrov 8957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Early exit if we're not supposed to run on this build flavor 8967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (is_debug_build != 1 && 8977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh config.getUnsignedValue("only_debug_build") == 1) { 8987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("early exit due to inappropriate build type"); 8997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return 0; 9007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 9017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 9027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned iterations = 0; 903f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen int seq = 0; 90407f00fd438a0c10bc6b2487352d09eb0a648db40Than McIntosh while(config.getUnsignedValue("main_loop_iterations") == 0 || 9057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh iterations < config.getUnsignedValue("main_loop_iterations")) { 9067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 9077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Figure out where in the collection interval we're going to actually 9087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // run perf 9097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned sleep_before_collect = 0; 9107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh unsigned sleep_after_collect = 0; 9117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh determine_before_after(sleep_before_collect, sleep_after_collect, 9127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh config.getUnsignedValue("collection_interval")); 9137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh perfprofd_sleep(sleep_before_collect); 9147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 915f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh // Reread config file -- the uploader may have rewritten it as a result 916f353d8bf370eab2117e6259630f5540f12b361b0Than McIntosh // of a gservices change 9178c7c7db1f1a23ab0c575cc217bed6b45f42b9ba5Than McIntosh config.readFile(); 9187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 9197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Check for profiling enabled... 9207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh CKPROFILE_RESULT ckresult = check_profiling_enabled(config); 9217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (ckresult != DO_COLLECT_PROFILE) { 9227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("profile collection skipped (%s)", 9237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh ckprofile_result_to_string(ckresult)); 9247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } else { 9257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh // Kick off the profiling run... 9267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("initiating profile collection"); 927f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen PROFILE_RESULT result = collect_profile(config, seq); 9287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh if (result != OK_PROFILE_COLLECTION) { 9297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("profile collection failed (%s)", 9307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh profile_result_to_string(result)); 9317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } else { 932f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen if (post_process(config, seq)) { 933f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen seq++; 934f4605017b29dd98232af9385e71079a3ba0297f1Dehao Chen } 9357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("profile collection complete"); 9367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 9377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 9387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh perfprofd_sleep(sleep_after_collect); 9397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh iterations += 1; 9407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh } 9417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh 9427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh W_ALOGI("finishing Android Wide Profiling daemon"); 9437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh return 0; 9447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh} 945