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