Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      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 DEBUG false  // STOPSHIP if true
     18 #include "Log.h"
     19 
     20 #include "StatsService.h"
     21 #include "stats_log_util.h"
     22 #include "android-base/stringprintf.h"
     23 #include "config/ConfigKey.h"
     24 #include "config/ConfigManager.h"
     25 #include "guardrail/StatsdStats.h"
     26 #include "storage/StorageManager.h"
     27 #include "subscriber/SubscriberReporter.h"
     28 
     29 #include <android-base/file.h>
     30 #include <android-base/stringprintf.h>
     31 #include <binder/IPCThreadState.h>
     32 #include <binder/IServiceManager.h>
     33 #include <binder/PermissionController.h>
     34 #include <dirent.h>
     35 #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
     36 #include <private/android_filesystem_config.h>
     37 #include <utils/Looper.h>
     38 #include <utils/String16.h>
     39 #include <statslog.h>
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <sys/system_properties.h>
     43 #include <unistd.h>
     44 
     45 using namespace android;
     46 
     47 using android::base::StringPrintf;
     48 
     49 namespace android {
     50 namespace os {
     51 namespace statsd {
     52 
     53 constexpr const char* kPermissionDump = "android.permission.DUMP";
     54 constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS";
     55 
     56 constexpr const char* kOpUsage = "android:get_usage_stats";
     57 
     58 #define STATS_SERVICE_DIR "/data/misc/stats-service"
     59 
     60 static binder::Status ok() {
     61     return binder::Status::ok();
     62 }
     63 
     64 static binder::Status exception(uint32_t code, const std::string& msg) {
     65     ALOGE("%s (%d)", msg.c_str(), code);
     66     return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
     67 }
     68 
     69 binder::Status checkUid(uid_t expectedUid) {
     70     uid_t uid = IPCThreadState::self()->getCallingUid();
     71     if (uid == expectedUid || uid == AID_ROOT) {
     72         return ok();
     73     } else {
     74         return exception(binder::Status::EX_SECURITY,
     75                 StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
     76     }
     77 }
     78 
     79 binder::Status checkDumpAndUsageStats(const String16& packageName) {
     80     pid_t pid = IPCThreadState::self()->getCallingPid();
     81     uid_t uid = IPCThreadState::self()->getCallingUid();
     82 
     83     // Root, system, and shell always have access
     84     if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) {
     85         return ok();
     86     }
     87 
     88     // Caller must be granted these permissions
     89     if (!checkCallingPermission(String16(kPermissionDump))) {
     90         return exception(binder::Status::EX_SECURITY,
     91                 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump));
     92     }
     93     if (!checkCallingPermission(String16(kPermissionUsage))) {
     94         return exception(binder::Status::EX_SECURITY,
     95                 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage));
     96     }
     97 
     98     // Caller must also have usage stats op granted
     99     PermissionController pc;
    100     switch (pc.noteOp(String16(kOpUsage), uid, packageName)) {
    101         case PermissionController::MODE_ALLOWED:
    102         case PermissionController::MODE_DEFAULT:
    103             return ok();
    104         default:
    105             return exception(binder::Status::EX_SECURITY,
    106                     StringPrintf("UID %d / PID %d lacks app-op %s", uid, pid, kOpUsage));
    107     }
    108 }
    109 
    110 #define ENFORCE_UID(uid) {                                        \
    111     binder::Status status = checkUid((uid));                      \
    112     if (!status.isOk()) {                                         \
    113         return status;                                            \
    114     }                                                             \
    115 }
    116 
    117 #define ENFORCE_DUMP_AND_USAGE_STATS(packageName) {               \
    118     binder::Status status = checkDumpAndUsageStats(packageName);  \
    119     if (!status.isOk()) {                                         \
    120         return status;                                            \
    121     }                                                             \
    122 }
    123 
    124 StatsService::StatsService(const sp<Looper>& handlerLooper)
    125     : mAnomalyAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
    126        [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) {
    127            if (sc != nullptr) {
    128                sc->setAnomalyAlarm(timeMillis);
    129                StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
    130            }
    131        },
    132        [](const sp<IStatsCompanionService>& sc) {
    133            if (sc != nullptr) {
    134                sc->cancelAnomalyAlarm();
    135                StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
    136            }
    137        })),
    138    mPeriodicAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
    139       [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) {
    140            if (sc != nullptr) {
    141                sc->setAlarmForSubscriberTriggering(timeMillis);
    142                StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged();
    143            }
    144       },
    145       [](const sp<IStatsCompanionService>& sc) {
    146            if (sc != nullptr) {
    147                sc->cancelAlarmForSubscriberTriggering();
    148                StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged();
    149            }
    150 
    151       }))  {
    152     mUidMap = new UidMap();
    153     StatsPuller::SetUidMap(mUidMap);
    154     mConfigManager = new ConfigManager();
    155     mProcessor = new StatsLogProcessor(mUidMap, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
    156                                        getElapsedRealtimeNs(), [this](const ConfigKey& key) {
    157         sp<IStatsCompanionService> sc = getStatsCompanionService();
    158         auto receiver = mConfigManager->GetConfigReceiver(key);
    159         if (sc == nullptr) {
    160             VLOG("Could not find StatsCompanionService");
    161             return false;
    162         } else if (receiver == nullptr) {
    163             VLOG("Statscompanion could not find a broadcast receiver for %s",
    164                  key.ToString().c_str());
    165             return false;
    166         } else {
    167             sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
    168             return true;
    169         }
    170     }
    171     );
    172 
    173     mConfigManager->AddListener(mProcessor);
    174 
    175     init_system_properties();
    176 }
    177 
    178 StatsService::~StatsService() {
    179 }
    180 
    181 void StatsService::init_system_properties() {
    182     mEngBuild = false;
    183     const prop_info* buildType = __system_property_find("ro.build.type");
    184     if (buildType != NULL) {
    185         __system_property_read_callback(buildType, init_build_type_callback, this);
    186     }
    187 }
    188 
    189 void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
    190                                             uint32_t serial) {
    191     if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) {
    192         reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
    193     }
    194 }
    195 
    196 /**
    197  * Implement our own because the default binder implementation isn't
    198  * properly handling SHELL_COMMAND_TRANSACTION.
    199  */
    200 status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
    201                                   uint32_t flags) {
    202     switch (code) {
    203         case SHELL_COMMAND_TRANSACTION: {
    204             int in = data.readFileDescriptor();
    205             int out = data.readFileDescriptor();
    206             int err = data.readFileDescriptor();
    207             int argc = data.readInt32();
    208             Vector<String8> args;
    209             for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
    210                 args.add(String8(data.readString16()));
    211             }
    212             sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
    213             sp<IResultReceiver> resultReceiver =
    214                     IResultReceiver::asInterface(data.readStrongBinder());
    215 
    216             FILE* fin = fdopen(in, "r");
    217             FILE* fout = fdopen(out, "w");
    218             FILE* ferr = fdopen(err, "w");
    219 
    220             if (fin == NULL || fout == NULL || ferr == NULL) {
    221                 resultReceiver->send(NO_MEMORY);
    222             } else {
    223                 err = command(fin, fout, ferr, args);
    224                 resultReceiver->send(err);
    225             }
    226 
    227             if (fin != NULL) {
    228                 fflush(fin);
    229                 fclose(fin);
    230             }
    231             if (fout != NULL) {
    232                 fflush(fout);
    233                 fclose(fout);
    234             }
    235             if (fout != NULL) {
    236                 fflush(ferr);
    237                 fclose(ferr);
    238             }
    239 
    240             return NO_ERROR;
    241         }
    242         default: { return BnStatsManager::onTransact(code, data, reply, flags); }
    243     }
    244 }
    245 
    246 /**
    247  * Write debugging data about statsd.
    248  */
    249 status_t StatsService::dump(int fd, const Vector<String16>& args) {
    250     if (!checkCallingPermission(String16(kPermissionDump))) {
    251         return PERMISSION_DENIED;
    252     }
    253     FILE* out = fdopen(fd, "w");
    254     if (out == NULL) {
    255         return NO_MEMORY;  // the fd is already open
    256     }
    257 
    258     bool verbose = false;
    259     bool proto = false;
    260     if (args.size() > 0 && !args[0].compare(String16("-v"))) {
    261         verbose = true;
    262     }
    263     if (args.size() > 0 && !args[args.size()-1].compare(String16("--proto"))) {
    264         proto = true;
    265     }
    266 
    267     dump_impl(out, verbose, proto);
    268 
    269     fclose(out);
    270     return NO_ERROR;
    271 }
    272 
    273 /**
    274  * Write debugging data about statsd in text or proto format.
    275  */
    276 void StatsService::dump_impl(FILE* out, bool verbose, bool proto) {
    277     if (proto) {
    278         vector<uint8_t> data;
    279         StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats.
    280         for (size_t i = 0; i < data.size(); i ++) {
    281             fprintf(out, "%c", data[i]);
    282         }
    283     } else {
    284         StatsdStats::getInstance().dumpStats(out);
    285         mProcessor->dumpStates(out, verbose);
    286     }
    287 }
    288 
    289 /**
    290  * Implementation of the adb shell cmd stats command.
    291  */
    292 status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
    293     uid_t uid = IPCThreadState::self()->getCallingUid();
    294     if (uid != AID_ROOT && uid != AID_SHELL) {
    295         return PERMISSION_DENIED;
    296     }
    297 
    298     const int argCount = args.size();
    299     if (argCount >= 1) {
    300         // adb shell cmd stats config ...
    301         if (!args[0].compare(String8("config"))) {
    302             return cmd_config(in, out, err, args);
    303         }
    304 
    305         if (!args[0].compare(String8("print-uid-map"))) {
    306             return cmd_print_uid_map(out, args);
    307         }
    308 
    309         if (!args[0].compare(String8("dump-report"))) {
    310             return cmd_dump_report(out, err, args);
    311         }
    312 
    313         if (!args[0].compare(String8("pull-source")) && args.size() > 1) {
    314             return cmd_print_pulled_metrics(out, args);
    315         }
    316 
    317         if (!args[0].compare(String8("send-broadcast"))) {
    318             return cmd_trigger_broadcast(out, args);
    319         }
    320 
    321         if (!args[0].compare(String8("print-stats"))) {
    322             return cmd_print_stats(out, args);
    323         }
    324 
    325         if (!args[0].compare(String8("meminfo"))) {
    326             return cmd_dump_memory_info(out);
    327         }
    328 
    329         if (!args[0].compare(String8("write-to-disk"))) {
    330             return cmd_write_data_to_disk(out);
    331         }
    332 
    333         if (!args[0].compare(String8("log-app-breadcrumb"))) {
    334             return cmd_log_app_breadcrumb(out, args);
    335         }
    336 
    337         if (!args[0].compare(String8("clear-puller-cache"))) {
    338             return cmd_clear_puller_cache(out);
    339         }
    340 
    341         if (!args[0].compare(String8("print-logs"))) {
    342             return cmd_print_logs(out, args);
    343         }
    344     }
    345 
    346     print_cmd_help(out);
    347     return NO_ERROR;
    348 }
    349 
    350 void StatsService::print_cmd_help(FILE* out) {
    351     fprintf(out,
    352             "usage: adb shell cmd stats print-stats-log [tag_required] "
    353             "[timestamp_nsec_optional]\n");
    354     fprintf(out, "\n");
    355     fprintf(out, "\n");
    356     fprintf(out, "usage: adb shell cmd stats meminfo\n");
    357     fprintf(out, "\n");
    358     fprintf(out, "  Prints the malloc debug information. You need to run the following first: \n");
    359     fprintf(out, "   # adb shell stop\n");
    360     fprintf(out, "   # adb shell setprop libc.debug.malloc.program statsd \n");
    361     fprintf(out, "   # adb shell setprop libc.debug.malloc.options backtrace \n");
    362     fprintf(out, "   # adb shell start\n");
    363     fprintf(out, "\n");
    364     fprintf(out, "\n");
    365     fprintf(out, "usage: adb shell cmd stats print-uid-map [PKG]\n");
    366     fprintf(out, "\n");
    367     fprintf(out, "  Prints the UID, app name, version mapping.\n");
    368     fprintf(out, "  PKG           Optional package name to print the uids of the package\n");
    369     fprintf(out, "\n");
    370     fprintf(out, "\n");
    371     fprintf(out, "usage: adb shell cmd stats pull-source [int] \n");
    372     fprintf(out, "\n");
    373     fprintf(out, "  Prints the output of a pulled metrics source (int indicates source)\n");
    374     fprintf(out, "\n");
    375     fprintf(out, "\n");
    376     fprintf(out, "usage: adb shell cmd stats write-to-disk \n");
    377     fprintf(out, "\n");
    378     fprintf(out, "  Flushes all data on memory to disk.\n");
    379     fprintf(out, "\n");
    380     fprintf(out, "\n");
    381     fprintf(out, "usage: adb shell cmd stats log-app-breadcrumb [UID] LABEL STATE\n");
    382     fprintf(out, "  Writes an AppBreadcrumbReported event to the statslog buffer.\n");
    383     fprintf(out, "  UID           The uid to use. It is only possible to pass a UID\n");
    384     fprintf(out, "                parameter on eng builds. If UID is omitted the calling\n");
    385     fprintf(out, "                uid is used.\n");
    386     fprintf(out, "  LABEL         Integer in [0, 15], as per atoms.proto.\n");
    387     fprintf(out, "  STATE         Integer in [0, 3], as per atoms.proto.\n");
    388     fprintf(out, "\n");
    389     fprintf(out, "\n");
    390     fprintf(out, "usage: adb shell cmd stats config remove [UID] [NAME]\n");
    391     fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
    392     fprintf(out, "\n");
    393     fprintf(out, "  Adds, updates or removes a configuration. The proto should be in\n");
    394     fprintf(out, "  wire-encoded protobuf format and passed via stdin. If no UID and name is\n");
    395     fprintf(out, "  provided, then all configs will be removed from memory and disk.\n");
    396     fprintf(out, "\n");
    397     fprintf(out, "  UID           The uid to use. It is only possible to pass the UID\n");
    398     fprintf(out, "                parameter on eng builds. If UID is omitted the calling\n");
    399     fprintf(out, "                uid is used.\n");
    400     fprintf(out, "  NAME          The per-uid name to use\n");
    401     fprintf(out, "\n");
    402     fprintf(out, "\n              *Note: If both UID and NAME are omitted then all configs will\n");
    403     fprintf(out, "\n                     be removed from memory and disk!\n");
    404     fprintf(out, "\n");
    405     fprintf(out, "usage: adb shell cmd stats dump-report [UID] NAME [--proto]\n");
    406     fprintf(out, "  Dump all metric data for a configuration.\n");
    407     fprintf(out, "  UID           The uid of the configuration. It is only possible to pass\n");
    408     fprintf(out, "                the UID parameter on eng builds. If UID is omitted the\n");
    409     fprintf(out, "                calling uid is used.\n");
    410     fprintf(out, "  NAME          The name of the configuration\n");
    411     fprintf(out, "  --proto       Print proto binary.\n");
    412     fprintf(out, "\n");
    413     fprintf(out, "\n");
    414     fprintf(out, "usage: adb shell cmd stats send-broadcast [UID] NAME\n");
    415     fprintf(out, "  Send a broadcast that triggers the subscriber to fetch metrics.\n");
    416     fprintf(out, "  UID           The uid of the configuration. It is only possible to pass\n");
    417     fprintf(out, "                the UID parameter on eng builds. If UID is omitted the\n");
    418     fprintf(out, "                calling uid is used.\n");
    419     fprintf(out, "  NAME          The name of the configuration\n");
    420     fprintf(out, "\n");
    421     fprintf(out, "\n");
    422     fprintf(out, "usage: adb shell cmd stats print-stats\n");
    423     fprintf(out, "  Prints some basic stats.\n");
    424     fprintf(out, "  --proto       Print proto binary instead of string format.\n");
    425     fprintf(out, "\n");
    426     fprintf(out, "\n");
    427     fprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
    428     fprintf(out, "  Clear cached puller data.\n");
    429     fprintf(out, "\n");
    430     fprintf(out, "usage: adb shell cmd stats print-logs\n");
    431     fprintf(out, "      Only works on eng build\n");
    432 }
    433 
    434 status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
    435     string name;
    436     bool good = false;
    437     int uid;
    438     const int argCount = args.size();
    439     if (argCount == 2) {
    440         // Automatically pick the UID
    441         uid = IPCThreadState::self()->getCallingUid();
    442         // TODO: What if this isn't a binder call? Should we fail?
    443         name.assign(args[1].c_str(), args[1].size());
    444         good = true;
    445     } else if (argCount == 3) {
    446         // If it's a userdebug or eng build, then the shell user can
    447         // impersonate other uids.
    448         if (mEngBuild) {
    449             const char* s = args[1].c_str();
    450             if (*s != '\0') {
    451                 char* end = NULL;
    452                 uid = strtol(s, &end, 0);
    453                 if (*end == '\0') {
    454                     name.assign(args[2].c_str(), args[2].size());
    455                     good = true;
    456                 }
    457             }
    458         } else {
    459             fprintf(out,
    460                     "The metrics can only be dumped for other UIDs on eng or userdebug "
    461                             "builds.\n");
    462         }
    463     }
    464     if (!good) {
    465         print_cmd_help(out);
    466         return UNKNOWN_ERROR;
    467     }
    468     ConfigKey key(uid, StrToInt64(name));
    469     auto receiver = mConfigManager->GetConfigReceiver(key);
    470     sp<IStatsCompanionService> sc = getStatsCompanionService();
    471     if (sc == nullptr) {
    472         VLOG("Could not access statsCompanion");
    473     } else if (receiver == nullptr) {
    474         VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str())
    475     } else {
    476         sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key));
    477         VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(),
    478              args[2].c_str());
    479     }
    480 
    481     return NO_ERROR;
    482 }
    483 
    484 status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
    485     const int argCount = args.size();
    486     if (argCount >= 2) {
    487         if (args[1] == "update" || args[1] == "remove") {
    488             bool good = false;
    489             int uid = -1;
    490             string name;
    491 
    492             if (argCount == 3) {
    493                 // Automatically pick the UID
    494                 uid = IPCThreadState::self()->getCallingUid();
    495                 // TODO: What if this isn't a binder call? Should we fail?
    496                 name.assign(args[2].c_str(), args[2].size());
    497                 good = true;
    498             } else if (argCount == 4) {
    499                 // If it's a userdebug or eng build, then the shell user can
    500                 // impersonate other uids.
    501                 if (mEngBuild) {
    502                     const char* s = args[2].c_str();
    503                     if (*s != '\0') {
    504                         char* end = NULL;
    505                         uid = strtol(s, &end, 0);
    506                         if (*end == '\0') {
    507                             name.assign(args[3].c_str(), args[3].size());
    508                             good = true;
    509                         }
    510                     }
    511                 } else {
    512                     fprintf(err,
    513                             "The config can only be set for other UIDs on eng or userdebug "
    514                             "builds.\n");
    515                 }
    516             } else if (argCount == 2 && args[1] == "remove") {
    517                 good = true;
    518             }
    519 
    520             if (!good) {
    521                 // If arg parsing failed, print the help text and return an error.
    522                 print_cmd_help(out);
    523                 return UNKNOWN_ERROR;
    524             }
    525 
    526             if (args[1] == "update") {
    527                 char* endp;
    528                 int64_t configID = strtoll(name.c_str(), &endp, 10);
    529                 if (endp == name.c_str() || *endp != '\0') {
    530                     fprintf(err, "Error parsing config ID.\n");
    531                     return UNKNOWN_ERROR;
    532                 }
    533 
    534                 // Read stream into buffer.
    535                 string buffer;
    536                 if (!android::base::ReadFdToString(fileno(in), &buffer)) {
    537                     fprintf(err, "Error reading stream for StatsConfig.\n");
    538                     return UNKNOWN_ERROR;
    539                 }
    540 
    541                 // Parse buffer.
    542                 StatsdConfig config;
    543                 if (!config.ParseFromString(buffer)) {
    544                     fprintf(err, "Error parsing proto stream for StatsConfig.\n");
    545                     return UNKNOWN_ERROR;
    546                 }
    547 
    548                 // Add / update the config.
    549                 mConfigManager->UpdateConfig(ConfigKey(uid, configID), config);
    550             } else {
    551                 if (argCount == 2) {
    552                     cmd_remove_all_configs(out);
    553                 } else {
    554                     // Remove the config.
    555                     mConfigManager->RemoveConfig(ConfigKey(uid, StrToInt64(name)));
    556                 }
    557             }
    558 
    559             return NO_ERROR;
    560         }
    561     }
    562     print_cmd_help(out);
    563     return UNKNOWN_ERROR;
    564 }
    565 
    566 status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args) {
    567     if (mProcessor != nullptr) {
    568         int argCount = args.size();
    569         bool good = false;
    570         bool proto = false;
    571         int uid;
    572         string name;
    573         if (!std::strcmp("--proto", args[argCount-1].c_str())) {
    574             proto = true;
    575             argCount -= 1;
    576         }
    577         if (argCount == 2) {
    578             // Automatically pick the UID
    579             uid = IPCThreadState::self()->getCallingUid();
    580             // TODO: What if this isn't a binder call? Should we fail?
    581             name.assign(args[1].c_str(), args[1].size());
    582             good = true;
    583         } else if (argCount == 3) {
    584             // If it's a userdebug or eng build, then the shell user can
    585             // impersonate other uids.
    586             if (mEngBuild) {
    587                 const char* s = args[1].c_str();
    588                 if (*s != '\0') {
    589                     char* end = NULL;
    590                     uid = strtol(s, &end, 0);
    591                     if (*end == '\0') {
    592                         name.assign(args[2].c_str(), args[2].size());
    593                         good = true;
    594                     }
    595                 }
    596             } else {
    597                 fprintf(out,
    598                         "The metrics can only be dumped for other UIDs on eng or userdebug "
    599                         "builds.\n");
    600             }
    601         }
    602         if (good) {
    603             vector<uint8_t> data;
    604             mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
    605                                      false /* include_current_bucket*/, ADB_DUMP, &data);
    606             // TODO: print the returned StatsLogReport to file instead of printing to logcat.
    607             if (proto) {
    608                 for (size_t i = 0; i < data.size(); i ++) {
    609                     fprintf(out, "%c", data[i]);
    610                 }
    611             } else {
    612                 fprintf(out, "Dump report for Config [%d,%s]\n", uid, name.c_str());
    613                 fprintf(out, "See the StatsLogReport in logcat...\n");
    614             }
    615             return android::OK;
    616         } else {
    617             // If arg parsing failed, print the help text and return an error.
    618             print_cmd_help(out);
    619             return UNKNOWN_ERROR;
    620         }
    621     } else {
    622         fprintf(out, "Log processor does not exist...\n");
    623         return UNKNOWN_ERROR;
    624     }
    625 }
    626 
    627 status_t StatsService::cmd_print_stats(FILE* out, const Vector<String8>& args) {
    628     int argCount = args.size();
    629     bool proto = false;
    630     if (!std::strcmp("--proto", args[argCount-1].c_str())) {
    631         proto = true;
    632         argCount -= 1;
    633     }
    634     StatsdStats& statsdStats = StatsdStats::getInstance();
    635     if (proto) {
    636         vector<uint8_t> data;
    637         statsdStats.dumpStats(&data, false); // does not reset statsdStats.
    638         for (size_t i = 0; i < data.size(); i ++) {
    639             fprintf(out, "%c", data[i]);
    640         }
    641 
    642     } else {
    643         vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
    644         for (const ConfigKey& key : configs) {
    645             fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
    646                     mProcessor->GetMetricsSize(key));
    647         }
    648         statsdStats.dumpStats(out);
    649     }
    650     return NO_ERROR;
    651 }
    652 
    653 status_t StatsService::cmd_print_uid_map(FILE* out, const Vector<String8>& args) {
    654     if (args.size() > 1) {
    655         string pkg;
    656         pkg.assign(args[1].c_str(), args[1].size());
    657         auto uids = mUidMap->getAppUid(pkg);
    658         fprintf(out, "%s -> [ ", pkg.c_str());
    659         for (const auto& uid : uids) {
    660             fprintf(out, "%d ", uid);
    661         }
    662         fprintf(out, "]\n");
    663     } else {
    664         mUidMap->printUidMap(out);
    665     }
    666     return NO_ERROR;
    667 }
    668 
    669 status_t StatsService::cmd_write_data_to_disk(FILE* out) {
    670     fprintf(out, "Writing data to disk\n");
    671     mProcessor->WriteDataToDisk(ADB_DUMP);
    672     return NO_ERROR;
    673 }
    674 
    675 status_t StatsService::cmd_log_app_breadcrumb(FILE* out, const Vector<String8>& args) {
    676     bool good = false;
    677     int32_t uid;
    678     int32_t label;
    679     int32_t state;
    680     const int argCount = args.size();
    681     if (argCount == 3) {
    682         // Automatically pick the UID
    683         uid = IPCThreadState::self()->getCallingUid();
    684         label = atoi(args[1].c_str());
    685         state = atoi(args[2].c_str());
    686         good = true;
    687     } else if (argCount == 4) {
    688         uid = atoi(args[1].c_str());
    689         // If it's a userdebug or eng build, then the shell user can impersonate other uids.
    690         // Otherwise, the uid must match the actual caller's uid.
    691         if (mEngBuild || (uid >= 0 && (uid_t)uid == IPCThreadState::self()->getCallingUid())) {
    692             label = atoi(args[2].c_str());
    693             state = atoi(args[3].c_str());
    694             good = true;
    695         } else {
    696             fprintf(out,
    697                     "Selecting a UID for writing AppBreadcrumb can only be done for other UIDs "
    698                             "on eng or userdebug builds.\n");
    699         }
    700     }
    701     if (good) {
    702         fprintf(out, "Logging AppBreadcrumbReported(%d, %d, %d) to statslog.\n", uid, label, state);
    703         android::util::stats_write(android::util::APP_BREADCRUMB_REPORTED, uid, label, state);
    704     } else {
    705         print_cmd_help(out);
    706         return UNKNOWN_ERROR;
    707     }
    708     return NO_ERROR;
    709 }
    710 
    711 status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) {
    712     int s = atoi(args[1].c_str());
    713     vector<shared_ptr<LogEvent> > stats;
    714     if (mStatsPullerManager.Pull(s, getElapsedRealtimeNs(), &stats)) {
    715         for (const auto& it : stats) {
    716             fprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
    717         }
    718         fprintf(out, "Pull from %d: Received %zu elements\n", s, stats.size());
    719         return NO_ERROR;
    720     }
    721     return UNKNOWN_ERROR;
    722 }
    723 
    724 status_t StatsService::cmd_remove_all_configs(FILE* out) {
    725     fprintf(out, "Removing all configs...\n");
    726     VLOG("StatsService::cmd_remove_all_configs was called");
    727     mConfigManager->RemoveAllConfigs();
    728     StorageManager::deleteAllFiles(STATS_SERVICE_DIR);
    729     return NO_ERROR;
    730 }
    731 
    732 status_t StatsService::cmd_dump_memory_info(FILE* out) {
    733     fprintf(out, "meminfo not available.\n");
    734     return NO_ERROR;
    735 }
    736 
    737 status_t StatsService::cmd_clear_puller_cache(FILE* out) {
    738     IPCThreadState* ipc = IPCThreadState::self();
    739     VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i",
    740             ipc->getCallingPid(), ipc->getCallingUid());
    741     if (checkCallingPermission(String16(kPermissionDump))) {
    742         int cleared = mStatsPullerManager.ForceClearPullerCache();
    743         fprintf(out, "Puller removed %d cached data!\n", cleared);
    744         return NO_ERROR;
    745     } else {
    746         return PERMISSION_DENIED;
    747     }
    748 }
    749 
    750 status_t StatsService::cmd_print_logs(FILE* out, const Vector<String8>& args) {
    751     IPCThreadState* ipc = IPCThreadState::self();
    752     VLOG("StatsService::cmd_print_logs with Pid %i, Uid %i", ipc->getCallingPid(),
    753          ipc->getCallingUid());
    754     if (checkCallingPermission(String16(kPermissionDump))) {
    755         bool enabled = true;
    756         if (args.size() >= 2) {
    757             enabled = atoi(args[1].c_str()) != 0;
    758         }
    759         mProcessor->setPrintLogs(enabled);
    760         return NO_ERROR;
    761     } else {
    762         return PERMISSION_DENIED;
    763     }
    764 }
    765 
    766 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
    767                                       const vector<String16>& app) {
    768     ENFORCE_UID(AID_SYSTEM);
    769 
    770     VLOG("StatsService::informAllUidData was called");
    771     mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
    772     VLOG("StatsService::informAllUidData succeeded");
    773 
    774     return Status::ok();
    775 }
    776 
    777 Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
    778     ENFORCE_UID(AID_SYSTEM);
    779 
    780     VLOG("StatsService::informOnePackage was called");
    781     mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
    782     return Status::ok();
    783 }
    784 
    785 Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
    786     ENFORCE_UID(AID_SYSTEM);
    787 
    788     VLOG("StatsService::informOnePackageRemoved was called");
    789     mUidMap->removeApp(getElapsedRealtimeNs(), app, uid);
    790     mConfigManager->RemoveConfigs(uid);
    791     return Status::ok();
    792 }
    793 
    794 Status StatsService::informAnomalyAlarmFired() {
    795     ENFORCE_UID(AID_SYSTEM);
    796 
    797     VLOG("StatsService::informAnomalyAlarmFired was called");
    798     int64_t currentTimeSec = getElapsedRealtimeSec();
    799     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
    800             mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
    801     if (alarmSet.size() > 0) {
    802         VLOG("Found an anomaly alarm that fired.");
    803         mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
    804     } else {
    805         VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
    806     }
    807     return Status::ok();
    808 }
    809 
    810 Status StatsService::informAlarmForSubscriberTriggeringFired() {
    811     ENFORCE_UID(AID_SYSTEM);
    812 
    813     VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
    814     int64_t currentTimeSec = getElapsedRealtimeSec();
    815     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
    816             mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
    817     if (alarmSet.size() > 0) {
    818         VLOG("Found periodic alarm fired.");
    819         mProcessor->onPeriodicAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
    820     } else {
    821         ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
    822     }
    823     return Status::ok();
    824 }
    825 
    826 Status StatsService::informPollAlarmFired() {
    827     ENFORCE_UID(AID_SYSTEM);
    828 
    829     VLOG("StatsService::informPollAlarmFired was called");
    830     mProcessor->informPullAlarmFired(getElapsedRealtimeNs());
    831     VLOG("StatsService::informPollAlarmFired succeeded");
    832     return Status::ok();
    833 }
    834 
    835 Status StatsService::systemRunning() {
    836     ENFORCE_UID(AID_SYSTEM);
    837 
    838     // When system_server is up and running, schedule the dropbox task to run.
    839     VLOG("StatsService::systemRunning");
    840     sayHiToStatsCompanion();
    841     return Status::ok();
    842 }
    843 
    844 Status StatsService::informDeviceShutdown() {
    845     ENFORCE_UID(AID_SYSTEM);
    846     VLOG("StatsService::informDeviceShutdown");
    847     mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN);
    848     return Status::ok();
    849 }
    850 
    851 void StatsService::sayHiToStatsCompanion() {
    852     sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
    853     if (statsCompanion != nullptr) {
    854         VLOG("Telling statsCompanion that statsd is ready");
    855         statsCompanion->statsdReady();
    856     } else {
    857         VLOG("Could not access statsCompanion");
    858     }
    859 }
    860 
    861 Status StatsService::statsCompanionReady() {
    862     ENFORCE_UID(AID_SYSTEM);
    863 
    864     VLOG("StatsService::statsCompanionReady was called");
    865     sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
    866     if (statsCompanion == nullptr) {
    867         return Status::fromExceptionCode(
    868                 Status::EX_NULL_POINTER,
    869                 "statscompanion unavailable despite it contacting statsd!");
    870     }
    871     VLOG("StatsService::statsCompanionReady linking to statsCompanion.");
    872     IInterface::asBinder(statsCompanion)->linkToDeath(this);
    873     mStatsPullerManager.SetStatsCompanionService(statsCompanion);
    874     mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion);
    875     mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion);
    876     SubscriberReporter::getInstance().setStatsCompanionService(statsCompanion);
    877     return Status::ok();
    878 }
    879 
    880 void StatsService::Startup() {
    881     mConfigManager->Startup();
    882 }
    883 
    884 void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) {
    885     mProcessor->OnLogEvent(event, reconnectionStarts);
    886 }
    887 
    888 Status StatsService::getData(int64_t key, const String16& packageName, vector<uint8_t>* output) {
    889     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    890 
    891     IPCThreadState* ipc = IPCThreadState::self();
    892     VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
    893     ConfigKey configKey(ipc->getCallingUid(), key);
    894     mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/,
    895                              GET_DATA_CALLED, output);
    896     return Status::ok();
    897 }
    898 
    899 Status StatsService::getMetadata(const String16& packageName, vector<uint8_t>* output) {
    900     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    901 
    902     IPCThreadState* ipc = IPCThreadState::self();
    903     VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(),
    904          ipc->getCallingUid());
    905     StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters.
    906     return Status::ok();
    907 }
    908 
    909 Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config,
    910                                       const String16& packageName) {
    911     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    912 
    913     IPCThreadState* ipc = IPCThreadState::self();
    914     if (addConfigurationChecked(ipc->getCallingUid(), key, config)) {
    915         return Status::ok();
    916     } else {
    917         ALOGE("Could not parse malformatted StatsdConfig");
    918         return Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT,
    919                                          "config does not correspond to a StatsdConfig proto");
    920     }
    921 }
    922 
    923 bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<uint8_t>& config) {
    924     ConfigKey configKey(uid, key);
    925     StatsdConfig cfg;
    926     if (config.size() > 0) {  // If the config is empty, skip parsing.
    927         if (!cfg.ParseFromArray(&config[0], config.size())) {
    928             return false;
    929         }
    930     }
    931     mConfigManager->UpdateConfig(configKey, cfg);
    932     return true;
    933 }
    934 
    935 Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) {
    936     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    937 
    938     IPCThreadState* ipc = IPCThreadState::self();
    939     ConfigKey configKey(ipc->getCallingUid(), key);
    940     mConfigManager->RemoveConfigReceiver(configKey);
    941     return Status::ok();
    942 }
    943 
    944 Status StatsService::setDataFetchOperation(int64_t key,
    945                                            const sp<android::IBinder>& intentSender,
    946                                            const String16& packageName) {
    947     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    948 
    949     IPCThreadState* ipc = IPCThreadState::self();
    950     ConfigKey configKey(ipc->getCallingUid(), key);
    951     mConfigManager->SetConfigReceiver(configKey, intentSender);
    952     if (StorageManager::hasConfigMetricsReport(configKey)) {
    953         VLOG("StatsService::setDataFetchOperation marking configKey %s to dump reports on disk",
    954              configKey.ToString().c_str());
    955         mProcessor->noteOnDiskData(configKey);
    956     }
    957     return Status::ok();
    958 }
    959 
    960 Status StatsService::removeConfiguration(int64_t key, const String16& packageName) {
    961     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    962 
    963     IPCThreadState* ipc = IPCThreadState::self();
    964     ConfigKey configKey(ipc->getCallingUid(), key);
    965     mConfigManager->RemoveConfig(configKey);
    966     SubscriberReporter::getInstance().removeConfig(configKey);
    967     return Status::ok();
    968 }
    969 
    970 Status StatsService::setBroadcastSubscriber(int64_t configId,
    971                                             int64_t subscriberId,
    972                                             const sp<android::IBinder>& intentSender,
    973                                             const String16& packageName) {
    974     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    975 
    976     VLOG("StatsService::setBroadcastSubscriber called.");
    977     IPCThreadState* ipc = IPCThreadState::self();
    978     ConfigKey configKey(ipc->getCallingUid(), configId);
    979     SubscriberReporter::getInstance()
    980             .setBroadcastSubscriber(configKey, subscriberId, intentSender);
    981     return Status::ok();
    982 }
    983 
    984 Status StatsService::unsetBroadcastSubscriber(int64_t configId,
    985                                               int64_t subscriberId,
    986                                               const String16& packageName) {
    987     ENFORCE_DUMP_AND_USAGE_STATS(packageName);
    988 
    989     VLOG("StatsService::unsetBroadcastSubscriber called.");
    990     IPCThreadState* ipc = IPCThreadState::self();
    991     ConfigKey configKey(ipc->getCallingUid(), configId);
    992     SubscriberReporter::getInstance()
    993             .unsetBroadcastSubscriber(configKey, subscriberId);
    994     return Status::ok();
    995 }
    996 
    997 Status StatsService::sendAppBreadcrumbAtom(int32_t label, int32_t state) {
    998     // Permission check not necessary as it's meant for applications to write to
    999     // statsd.
   1000     android::util::stats_write(util::APP_BREADCRUMB_REPORTED,
   1001                                IPCThreadState::self()->getCallingUid(), label,
   1002                                state);
   1003     return Status::ok();
   1004 }
   1005 
   1006 void StatsService::binderDied(const wp <IBinder>& who) {
   1007     ALOGW("statscompanion service died");
   1008     StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
   1009     if (mProcessor != nullptr) {
   1010         ALOGW("Reset statsd upon system server restars.");
   1011         mProcessor->WriteDataToDisk(STATSCOMPANION_DIED);
   1012         mProcessor->resetConfigs();
   1013     }
   1014     mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
   1015     mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
   1016     SubscriberReporter::getInstance().setStatsCompanionService(nullptr);
   1017     mStatsPullerManager.SetStatsCompanionService(nullptr);
   1018 }
   1019 
   1020 }  // namespace statsd
   1021 }  // namespace os
   1022 }  // namespace android
   1023