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 <android-base/strings.h> 32 #include <binder/IPCThreadState.h> 33 #include <binder/IServiceManager.h> 34 #include <binder/PermissionController.h> 35 #include <cutils/multiuser.h> 36 #include <dirent.h> 37 #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> 38 #include <frameworks/base/cmds/statsd/src/uid_data.pb.h> 39 #include <private/android_filesystem_config.h> 40 #include <statslog.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <sys/system_properties.h> 44 #include <unistd.h> 45 #include <utils/Looper.h> 46 #include <utils/String16.h> 47 #include <chrono> 48 49 using namespace android; 50 51 using android::base::StringPrintf; 52 using android::util::FIELD_COUNT_REPEATED; 53 using android::util::FIELD_TYPE_INT64; 54 using android::util::FIELD_TYPE_MESSAGE; 55 using android::util::ProtoReader; 56 57 namespace android { 58 namespace os { 59 namespace statsd { 60 61 constexpr const char* kPermissionDump = "android.permission.DUMP"; 62 constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS"; 63 64 constexpr const char* kOpUsage = "android:get_usage_stats"; 65 66 #define STATS_SERVICE_DIR "/data/misc/stats-service" 67 68 // for StatsDataDumpProto 69 const int FIELD_ID_REPORTS_LIST = 1; 70 71 static binder::Status ok() { 72 return binder::Status::ok(); 73 } 74 75 static binder::Status exception(uint32_t code, const std::string& msg) { 76 ALOGE("%s (%d)", msg.c_str(), code); 77 return binder::Status::fromExceptionCode(code, String8(msg.c_str())); 78 } 79 80 binder::Status checkUid(uid_t expectedUid) { 81 uid_t uid = IPCThreadState::self()->getCallingUid(); 82 if (uid == expectedUid || uid == AID_ROOT) { 83 return ok(); 84 } else { 85 return exception(binder::Status::EX_SECURITY, 86 StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); 87 } 88 } 89 90 binder::Status checkDumpAndUsageStats(const String16& packageName) { 91 pid_t pid = IPCThreadState::self()->getCallingPid(); 92 uid_t uid = IPCThreadState::self()->getCallingUid(); 93 94 // Root, system, and shell always have access 95 if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) { 96 return ok(); 97 } 98 99 // Caller must be granted these permissions 100 if (!checkCallingPermission(String16(kPermissionDump))) { 101 return exception(binder::Status::EX_SECURITY, 102 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump)); 103 } 104 if (!checkCallingPermission(String16(kPermissionUsage))) { 105 return exception(binder::Status::EX_SECURITY, 106 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage)); 107 } 108 109 // Caller must also have usage stats op granted 110 PermissionController pc; 111 switch (pc.noteOp(String16(kOpUsage), uid, packageName)) { 112 case PermissionController::MODE_ALLOWED: 113 case PermissionController::MODE_DEFAULT: 114 return ok(); 115 default: 116 return exception(binder::Status::EX_SECURITY, 117 StringPrintf("UID %d / PID %d lacks app-op %s", uid, pid, kOpUsage)); 118 } 119 } 120 121 #define ENFORCE_UID(uid) { \ 122 binder::Status status = checkUid((uid)); \ 123 if (!status.isOk()) { \ 124 return status; \ 125 } \ 126 } 127 128 #define ENFORCE_DUMP_AND_USAGE_STATS(packageName) { \ 129 binder::Status status = checkDumpAndUsageStats(packageName); \ 130 if (!status.isOk()) { \ 131 return status; \ 132 } \ 133 } 134 135 StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue) 136 : mAnomalyAlarmMonitor(new AlarmMonitor( 137 MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS, 138 [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) { 139 if (sc != nullptr) { 140 sc->setAnomalyAlarm(timeMillis); 141 StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged(); 142 } 143 }, 144 [](const sp<IStatsCompanionService>& sc) { 145 if (sc != nullptr) { 146 sc->cancelAnomalyAlarm(); 147 StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged(); 148 } 149 })), 150 mPeriodicAlarmMonitor(new AlarmMonitor( 151 MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS, 152 [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) { 153 if (sc != nullptr) { 154 sc->setAlarmForSubscriberTriggering(timeMillis); 155 StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged(); 156 } 157 }, 158 [](const sp<IStatsCompanionService>& sc) { 159 if (sc != nullptr) { 160 sc->cancelAlarmForSubscriberTriggering(); 161 StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged(); 162 } 163 })), 164 mEventQueue(queue) { 165 mUidMap = UidMap::getInstance(); 166 mPullerManager = new StatsPullerManager(); 167 StatsPuller::SetUidMap(mUidMap); 168 mConfigManager = new ConfigManager(); 169 mProcessor = new StatsLogProcessor( 170 mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor, 171 getElapsedRealtimeNs(), 172 [this](const ConfigKey& key) { 173 sp<IStatsCompanionService> sc = getStatsCompanionService(); 174 auto receiver = mConfigManager->GetConfigReceiver(key); 175 if (sc == nullptr) { 176 VLOG("Could not find StatsCompanionService"); 177 return false; 178 } else if (receiver == nullptr) { 179 VLOG("Statscompanion could not find a broadcast receiver for %s", 180 key.ToString().c_str()); 181 return false; 182 } else { 183 sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key)); 184 return true; 185 } 186 }, 187 [this](const int& uid, const vector<int64_t>& activeConfigs) { 188 auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid); 189 sp<IStatsCompanionService> sc = getStatsCompanionService(); 190 if (sc == nullptr) { 191 VLOG("Could not access statsCompanion"); 192 return false; 193 } else if (receiver == nullptr) { 194 VLOG("Could not find receiver for uid %d", uid); 195 return false; 196 } else { 197 sc->sendActiveConfigsChangedBroadcast(receiver, activeConfigs); 198 VLOG("StatsService::active configs broadcast succeeded for uid %d" , uid); 199 return true; 200 } 201 }); 202 203 mConfigManager->AddListener(mProcessor); 204 205 init_system_properties(); 206 207 if (mEventQueue != nullptr) { 208 std::thread pushedEventThread([this] { readLogs(); }); 209 pushedEventThread.detach(); 210 } 211 } 212 213 StatsService::~StatsService() { 214 } 215 216 /* Runs on a dedicated thread to process pushed events. */ 217 void StatsService::readLogs() { 218 // Read forever..... long live statsd 219 while (1) { 220 // Block until an event is available. 221 auto event = mEventQueue->waitPop(); 222 // Pass it to StatsLogProcess to all configs/metrics 223 // At this point, the LogEventQueue is not blocked, so that the socketListener 224 // can read events from the socket and write to buffer to avoid data drop. 225 mProcessor->OnLogEvent(event.get()); 226 // The ShellSubscriber is only used by shell for local debugging. 227 if (mShellSubscriber != nullptr) { 228 mShellSubscriber->onLogEvent(*event); 229 } 230 } 231 } 232 233 void StatsService::init_system_properties() { 234 mEngBuild = false; 235 const prop_info* buildType = __system_property_find("ro.build.type"); 236 if (buildType != NULL) { 237 __system_property_read_callback(buildType, init_build_type_callback, this); 238 } 239 } 240 241 void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value, 242 uint32_t serial) { 243 if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) { 244 reinterpret_cast<StatsService*>(cookie)->mEngBuild = true; 245 } 246 } 247 248 /** 249 * Implement our own because the default binder implementation isn't 250 * properly handling SHELL_COMMAND_TRANSACTION. 251 */ 252 status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, 253 uint32_t flags) { 254 switch (code) { 255 case SHELL_COMMAND_TRANSACTION: { 256 int in = data.readFileDescriptor(); 257 int out = data.readFileDescriptor(); 258 int err = data.readFileDescriptor(); 259 int argc = data.readInt32(); 260 Vector<String8> args; 261 for (int i = 0; i < argc && data.dataAvail() > 0; i++) { 262 args.add(String8(data.readString16())); 263 } 264 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder()); 265 sp<IResultReceiver> resultReceiver = 266 IResultReceiver::asInterface(data.readStrongBinder()); 267 268 err = command(in, out, err, args, resultReceiver); 269 resultReceiver->send(err); 270 return NO_ERROR; 271 } 272 default: { return BnStatsManager::onTransact(code, data, reply, flags); } 273 } 274 } 275 276 /** 277 * Write data from statsd. 278 * Format for statsdStats: adb shell dumpsys stats --metadata [-v] [--proto] 279 * Format for data report: adb shell dumpsys stats [anything other than --metadata] [--proto] 280 * Anything ending in --proto will be in proto format. 281 * Anything without --metadata as the first argument will be report information. 282 * (bugreports call "adb shell dumpsys stats --dump-priority NORMAL -a --proto") 283 * TODO: Come up with a more robust method of enacting <serviceutils/PriorityDumper.h>. 284 */ 285 status_t StatsService::dump(int fd, const Vector<String16>& args) { 286 if (!checkCallingPermission(String16(kPermissionDump))) { 287 return PERMISSION_DENIED; 288 } 289 int lastArg = args.size() - 1; 290 bool asProto = false; 291 if (lastArg >= 0 && !args[lastArg].compare(String16("--proto"))) { // last argument 292 asProto = true; 293 lastArg--; 294 } 295 if (args.size() > 0 && !args[0].compare(String16("--metadata"))) { // first argument 296 // Request is to dump statsd stats. 297 bool verbose = false; 298 if (lastArg >= 0 && !args[lastArg].compare(String16("-v"))) { 299 verbose = true; 300 lastArg--; 301 } 302 dumpStatsdStats(fd, verbose, asProto); 303 } else { 304 // Request is to dump statsd report data. 305 if (asProto) { 306 dumpIncidentSection(fd); 307 } else { 308 dprintf(fd, "Non-proto format of stats data dump not available; see proto version.\n"); 309 } 310 } 311 312 return NO_ERROR; 313 } 314 315 /** 316 * Write debugging data about statsd in text or proto format. 317 */ 318 void StatsService::dumpStatsdStats(int out, bool verbose, bool proto) { 319 if (proto) { 320 vector<uint8_t> data; 321 StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats. 322 for (size_t i = 0; i < data.size(); i ++) { 323 dprintf(out, "%c", data[i]); 324 } 325 } else { 326 StatsdStats::getInstance().dumpStats(out); 327 mProcessor->dumpStates(out, verbose); 328 } 329 } 330 331 /** 332 * Write stats report data in StatsDataDumpProto incident section format. 333 */ 334 void StatsService::dumpIncidentSection(int out) { 335 ProtoOutputStream proto; 336 for (const ConfigKey& configKey : mConfigManager->GetAllConfigKeys()) { 337 uint64_t reportsListToken = 338 proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS_LIST); 339 mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), 340 true /* includeCurrentBucket */, false /* erase_data */, 341 ADB_DUMP, 342 FAST, 343 &proto); 344 proto.end(reportsListToken); 345 proto.flush(out); 346 proto.clear(); 347 } 348 } 349 350 /** 351 * Implementation of the adb shell cmd stats command. 352 */ 353 status_t StatsService::command(int in, int out, int err, Vector<String8>& args, 354 sp<IResultReceiver> resultReceiver) { 355 uid_t uid = IPCThreadState::self()->getCallingUid(); 356 if (uid != AID_ROOT && uid != AID_SHELL) { 357 return PERMISSION_DENIED; 358 } 359 360 const int argCount = args.size(); 361 if (argCount >= 1) { 362 // adb shell cmd stats config ... 363 if (!args[0].compare(String8("config"))) { 364 return cmd_config(in, out, err, args); 365 } 366 367 if (!args[0].compare(String8("print-uid-map"))) { 368 return cmd_print_uid_map(out, args); 369 } 370 371 if (!args[0].compare(String8("dump-report"))) { 372 return cmd_dump_report(out, args); 373 } 374 375 if (!args[0].compare(String8("pull-source")) && args.size() > 1) { 376 return cmd_print_pulled_metrics(out, args); 377 } 378 379 if (!args[0].compare(String8("send-broadcast"))) { 380 return cmd_trigger_broadcast(out, args); 381 } 382 383 if (!args[0].compare(String8("print-stats"))) { 384 return cmd_print_stats(out, args); 385 } 386 387 if (!args[0].compare(String8("meminfo"))) { 388 return cmd_dump_memory_info(out); 389 } 390 391 if (!args[0].compare(String8("write-to-disk"))) { 392 return cmd_write_data_to_disk(out); 393 } 394 395 if (!args[0].compare(String8("log-app-breadcrumb"))) { 396 return cmd_log_app_breadcrumb(out, args); 397 } 398 399 if (!args[0].compare(String8("log-binary-push"))) { 400 return cmd_log_binary_push(out, args); 401 } 402 403 if (!args[0].compare(String8("clear-puller-cache"))) { 404 return cmd_clear_puller_cache(out); 405 } 406 407 if (!args[0].compare(String8("print-logs"))) { 408 return cmd_print_logs(out, args); 409 } 410 if (!args[0].compare(String8("send-active-configs"))) { 411 return cmd_trigger_active_config_broadcast(out, args); 412 } 413 if (!args[0].compare(String8("data-subscribe"))) { 414 if (mShellSubscriber == nullptr) { 415 mShellSubscriber = new ShellSubscriber(mUidMap, mPullerManager); 416 } 417 int timeoutSec = -1; 418 if (argCount >= 2) { 419 timeoutSec = atoi(args[1].c_str()); 420 } 421 mShellSubscriber->startNewSubscription(in, out, resultReceiver, timeoutSec); 422 return NO_ERROR; 423 } 424 } 425 426 print_cmd_help(out); 427 return NO_ERROR; 428 } 429 430 void StatsService::print_cmd_help(int out) { 431 dprintf(out, 432 "usage: adb shell cmd stats print-stats-log [tag_required] " 433 "[timestamp_nsec_optional]\n"); 434 dprintf(out, "\n"); 435 dprintf(out, "\n"); 436 dprintf(out, "usage: adb shell cmd stats meminfo\n"); 437 dprintf(out, "\n"); 438 dprintf(out, " Prints the malloc debug information. You need to run the following first: \n"); 439 dprintf(out, " # adb shell stop\n"); 440 dprintf(out, " # adb shell setprop libc.debug.malloc.program statsd \n"); 441 dprintf(out, " # adb shell setprop libc.debug.malloc.options backtrace \n"); 442 dprintf(out, " # adb shell start\n"); 443 dprintf(out, "\n"); 444 dprintf(out, "\n"); 445 dprintf(out, "usage: adb shell cmd stats print-uid-map [PKG]\n"); 446 dprintf(out, "\n"); 447 dprintf(out, " Prints the UID, app name, version mapping.\n"); 448 dprintf(out, " PKG Optional package name to print the uids of the package\n"); 449 dprintf(out, "\n"); 450 dprintf(out, "\n"); 451 dprintf(out, "usage: adb shell cmd stats pull-source [int] \n"); 452 dprintf(out, "\n"); 453 dprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n"); 454 dprintf(out, "\n"); 455 dprintf(out, "\n"); 456 dprintf(out, "usage: adb shell cmd stats write-to-disk \n"); 457 dprintf(out, "\n"); 458 dprintf(out, " Flushes all data on memory to disk.\n"); 459 dprintf(out, "\n"); 460 dprintf(out, "\n"); 461 dprintf(out, "usage: adb shell cmd stats log-app-breadcrumb [UID] LABEL STATE\n"); 462 dprintf(out, " Writes an AppBreadcrumbReported event to the statslog buffer.\n"); 463 dprintf(out, " UID The uid to use. It is only possible to pass a UID\n"); 464 dprintf(out, " parameter on eng builds. If UID is omitted the calling\n"); 465 dprintf(out, " uid is used.\n"); 466 dprintf(out, " LABEL Integer in [0, 15], as per atoms.proto.\n"); 467 dprintf(out, " STATE Integer in [0, 3], as per atoms.proto.\n"); 468 dprintf(out, "\n"); 469 dprintf(out, "\n"); 470 dprintf(out, 471 "usage: adb shell cmd stats log-binary-push NAME VERSION STAGING ROLLBACK_ENABLED " 472 "LOW_LATENCY STATE EXPERIMENT_IDS\n"); 473 dprintf(out, " Log a binary push state changed event.\n"); 474 dprintf(out, " NAME The train name.\n"); 475 dprintf(out, " VERSION The train version code.\n"); 476 dprintf(out, " STAGING If this train requires a restart.\n"); 477 dprintf(out, " ROLLBACK_ENABLED If rollback should be enabled for this install.\n"); 478 dprintf(out, " LOW_LATENCY If the train requires low latency monitoring.\n"); 479 dprintf(out, " STATE The status of the train push.\n"); 480 dprintf(out, " Integer value of the enum in atoms.proto.\n"); 481 dprintf(out, " EXPERIMENT_IDS Comma separated list of experiment ids.\n"); 482 dprintf(out, " Leave blank for none.\n"); 483 dprintf(out, "\n"); 484 dprintf(out, "\n"); 485 dprintf(out, "usage: adb shell cmd stats config remove [UID] [NAME]\n"); 486 dprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n"); 487 dprintf(out, "\n"); 488 dprintf(out, " Adds, updates or removes a configuration. The proto should be in\n"); 489 dprintf(out, " wire-encoded protobuf format and passed via stdin. If no UID and name is\n"); 490 dprintf(out, " provided, then all configs will be removed from memory and disk.\n"); 491 dprintf(out, "\n"); 492 dprintf(out, " UID The uid to use. It is only possible to pass the UID\n"); 493 dprintf(out, " parameter on eng builds. If UID is omitted the calling\n"); 494 dprintf(out, " uid is used.\n"); 495 dprintf(out, " NAME The per-uid name to use\n"); 496 dprintf(out, "\n"); 497 dprintf(out, "\n *Note: If both UID and NAME are omitted then all configs will\n"); 498 dprintf(out, "\n be removed from memory and disk!\n"); 499 dprintf(out, "\n"); 500 dprintf(out, 501 "usage: adb shell cmd stats dump-report [UID] NAME [--keep_data] " 502 "[--include_current_bucket] [--proto]\n"); 503 dprintf(out, " Dump all metric data for a configuration.\n"); 504 dprintf(out, " UID The uid of the configuration. It is only possible to pass\n"); 505 dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n"); 506 dprintf(out, " calling uid is used.\n"); 507 dprintf(out, " NAME The name of the configuration\n"); 508 dprintf(out, " --keep_data Do NOT erase the data upon dumping it.\n"); 509 dprintf(out, " --proto Print proto binary.\n"); 510 dprintf(out, "\n"); 511 dprintf(out, "\n"); 512 dprintf(out, "usage: adb shell cmd stats send-broadcast [UID] NAME\n"); 513 dprintf(out, " Send a broadcast that triggers the subscriber to fetch metrics.\n"); 514 dprintf(out, " UID The uid of the configuration. It is only possible to pass\n"); 515 dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n"); 516 dprintf(out, " calling uid is used.\n"); 517 dprintf(out, " NAME The name of the configuration\n"); 518 dprintf(out, "\n"); 519 dprintf(out, "\n"); 520 dprintf(out, 521 "usage: adb shell cmd stats send-active-configs [--uid=UID] [--configs] " 522 "[NAME1] [NAME2] [NAME3..]\n"); 523 dprintf(out, " Send a broadcast that informs the subscriber of the current active configs.\n"); 524 dprintf(out, " --uid=UID The uid of the configurations. It is only possible to pass\n"); 525 dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n"); 526 dprintf(out, " calling uid is used.\n"); 527 dprintf(out, " --configs Send the list of configs in the name list instead of\n"); 528 dprintf(out, " the currently active configs\n"); 529 dprintf(out, " NAME LIST List of configuration names to be included in the broadcast.\n"); 530 dprintf(out, "\n"); 531 dprintf(out, "\n"); 532 dprintf(out, "usage: adb shell cmd stats print-stats\n"); 533 dprintf(out, " Prints some basic stats.\n"); 534 dprintf(out, " --proto Print proto binary instead of string format.\n"); 535 dprintf(out, "\n"); 536 dprintf(out, "\n"); 537 dprintf(out, "usage: adb shell cmd stats clear-puller-cache\n"); 538 dprintf(out, " Clear cached puller data.\n"); 539 dprintf(out, "\n"); 540 dprintf(out, "usage: adb shell cmd stats print-logs\n"); 541 dprintf(out, " Only works on eng build\n"); 542 } 543 544 status_t StatsService::cmd_trigger_broadcast(int out, Vector<String8>& args) { 545 string name; 546 bool good = false; 547 int uid; 548 const int argCount = args.size(); 549 if (argCount == 2) { 550 // Automatically pick the UID 551 uid = IPCThreadState::self()->getCallingUid(); 552 name.assign(args[1].c_str(), args[1].size()); 553 good = true; 554 } else if (argCount == 3) { 555 good = getUidFromArgs(args, 1, uid); 556 if (!good) { 557 dprintf(out, "Invalid UID. Note that the metrics can only be dumped for " 558 "other UIDs on eng or userdebug builds.\n"); 559 } 560 name.assign(args[2].c_str(), args[2].size()); 561 } 562 if (!good) { 563 print_cmd_help(out); 564 return UNKNOWN_ERROR; 565 } 566 ConfigKey key(uid, StrToInt64(name)); 567 auto receiver = mConfigManager->GetConfigReceiver(key); 568 sp<IStatsCompanionService> sc = getStatsCompanionService(); 569 if (sc == nullptr) { 570 VLOG("Could not access statsCompanion"); 571 } else if (receiver == nullptr) { 572 VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str()) 573 } else { 574 sc->sendDataBroadcast(receiver, mProcessor->getLastReportTimeNs(key)); 575 VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(), 576 args[2].c_str()); 577 } 578 579 return NO_ERROR; 580 } 581 582 status_t StatsService::cmd_trigger_active_config_broadcast(int out, Vector<String8>& args) { 583 const int argCount = args.size(); 584 int uid; 585 vector<int64_t> configIds; 586 if (argCount == 1) { 587 // Automatically pick the uid and send a broadcast that has no active configs. 588 uid = IPCThreadState::self()->getCallingUid(); 589 mProcessor->GetActiveConfigs(uid, configIds); 590 } else { 591 int curArg = 1; 592 if(args[curArg].find("--uid=") == 0) { 593 string uidArgStr(args[curArg].c_str()); 594 string uidStr = uidArgStr.substr(6); 595 if (!getUidFromString(uidStr.c_str(), uid)) { 596 dprintf(out, "Invalid UID. Note that the config can only be set for " 597 "other UIDs on eng or userdebug builds.\n"); 598 return UNKNOWN_ERROR; 599 } 600 curArg++; 601 } else { 602 uid = IPCThreadState::self()->getCallingUid(); 603 } 604 if (curArg == argCount || args[curArg] != "--configs") { 605 VLOG("Reached end of args, or specify configs not set. Sending actual active configs,"); 606 mProcessor->GetActiveConfigs(uid, configIds); 607 } else { 608 // Flag specified, use the given list of configs. 609 curArg++; 610 for (int i = curArg; i < argCount; i++) { 611 char* endp; 612 int64_t configID = strtoll(args[i].c_str(), &endp, 10); 613 if (endp == args[i].c_str() || *endp != '\0') { 614 dprintf(out, "Error parsing config ID.\n"); 615 return UNKNOWN_ERROR; 616 } 617 VLOG("Adding config id %ld", static_cast<long>(configID)); 618 configIds.push_back(configID); 619 } 620 } 621 } 622 auto receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid); 623 sp<IStatsCompanionService> sc = getStatsCompanionService(); 624 if (sc == nullptr) { 625 VLOG("Could not access statsCompanion"); 626 } else if (receiver == nullptr) { 627 VLOG("Could not find receiver for uid %d", uid); 628 } else { 629 sc->sendActiveConfigsChangedBroadcast(receiver, configIds); 630 VLOG("StatsService::trigger active configs changed broadcast succeeded for uid %d" , uid); 631 } 632 return NO_ERROR; 633 } 634 635 status_t StatsService::cmd_config(int in, int out, int err, Vector<String8>& args) { 636 const int argCount = args.size(); 637 if (argCount >= 2) { 638 if (args[1] == "update" || args[1] == "remove") { 639 bool good = false; 640 int uid = -1; 641 string name; 642 643 if (argCount == 3) { 644 // Automatically pick the UID 645 uid = IPCThreadState::self()->getCallingUid(); 646 name.assign(args[2].c_str(), args[2].size()); 647 good = true; 648 } else if (argCount == 4) { 649 good = getUidFromArgs(args, 2, uid); 650 if (!good) { 651 dprintf(err, "Invalid UID. Note that the config can only be set for " 652 "other UIDs on eng or userdebug builds.\n"); 653 } 654 name.assign(args[3].c_str(), args[3].size()); 655 } else if (argCount == 2 && args[1] == "remove") { 656 good = true; 657 } 658 659 if (!good) { 660 // If arg parsing failed, print the help text and return an error. 661 print_cmd_help(out); 662 return UNKNOWN_ERROR; 663 } 664 665 if (args[1] == "update") { 666 char* endp; 667 int64_t configID = strtoll(name.c_str(), &endp, 10); 668 if (endp == name.c_str() || *endp != '\0') { 669 dprintf(err, "Error parsing config ID.\n"); 670 return UNKNOWN_ERROR; 671 } 672 673 // Read stream into buffer. 674 string buffer; 675 if (!android::base::ReadFdToString(in, &buffer)) { 676 dprintf(err, "Error reading stream for StatsConfig.\n"); 677 return UNKNOWN_ERROR; 678 } 679 680 // Parse buffer. 681 StatsdConfig config; 682 if (!config.ParseFromString(buffer)) { 683 dprintf(err, "Error parsing proto stream for StatsConfig.\n"); 684 return UNKNOWN_ERROR; 685 } 686 687 // Add / update the config. 688 mConfigManager->UpdateConfig(ConfigKey(uid, configID), config); 689 } else { 690 if (argCount == 2) { 691 cmd_remove_all_configs(out); 692 } else { 693 // Remove the config. 694 mConfigManager->RemoveConfig(ConfigKey(uid, StrToInt64(name))); 695 } 696 } 697 698 return NO_ERROR; 699 } 700 } 701 print_cmd_help(out); 702 return UNKNOWN_ERROR; 703 } 704 705 status_t StatsService::cmd_dump_report(int out, const Vector<String8>& args) { 706 if (mProcessor != nullptr) { 707 int argCount = args.size(); 708 bool good = false; 709 bool proto = false; 710 bool includeCurrentBucket = false; 711 bool eraseData = true; 712 int uid; 713 string name; 714 if (!std::strcmp("--proto", args[argCount-1].c_str())) { 715 proto = true; 716 argCount -= 1; 717 } 718 if (!std::strcmp("--include_current_bucket", args[argCount-1].c_str())) { 719 includeCurrentBucket = true; 720 argCount -= 1; 721 } 722 if (!std::strcmp("--keep_data", args[argCount-1].c_str())) { 723 eraseData = false; 724 argCount -= 1; 725 } 726 if (argCount == 2) { 727 // Automatically pick the UID 728 uid = IPCThreadState::self()->getCallingUid(); 729 name.assign(args[1].c_str(), args[1].size()); 730 good = true; 731 } else if (argCount == 3) { 732 good = getUidFromArgs(args, 1, uid); 733 if (!good) { 734 dprintf(out, "Invalid UID. Note that the metrics can only be dumped for " 735 "other UIDs on eng or userdebug builds.\n"); 736 } 737 name.assign(args[2].c_str(), args[2].size()); 738 } 739 if (good) { 740 vector<uint8_t> data; 741 mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(), 742 includeCurrentBucket, eraseData, ADB_DUMP, 743 NO_TIME_CONSTRAINTS, 744 &data); 745 if (proto) { 746 for (size_t i = 0; i < data.size(); i ++) { 747 dprintf(out, "%c", data[i]); 748 } 749 } else { 750 dprintf(out, "Non-proto stats data dump not currently supported.\n"); 751 } 752 return android::OK; 753 } else { 754 // If arg parsing failed, print the help text and return an error. 755 print_cmd_help(out); 756 return UNKNOWN_ERROR; 757 } 758 } else { 759 dprintf(out, "Log processor does not exist...\n"); 760 return UNKNOWN_ERROR; 761 } 762 } 763 764 status_t StatsService::cmd_print_stats(int out, const Vector<String8>& args) { 765 int argCount = args.size(); 766 bool proto = false; 767 if (!std::strcmp("--proto", args[argCount-1].c_str())) { 768 proto = true; 769 argCount -= 1; 770 } 771 StatsdStats& statsdStats = StatsdStats::getInstance(); 772 if (proto) { 773 vector<uint8_t> data; 774 statsdStats.dumpStats(&data, false); // does not reset statsdStats. 775 for (size_t i = 0; i < data.size(); i ++) { 776 dprintf(out, "%c", data[i]); 777 } 778 779 } else { 780 vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys(); 781 for (const ConfigKey& key : configs) { 782 dprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(), 783 mProcessor->GetMetricsSize(key)); 784 } 785 statsdStats.dumpStats(out); 786 } 787 return NO_ERROR; 788 } 789 790 status_t StatsService::cmd_print_uid_map(int out, const Vector<String8>& args) { 791 if (args.size() > 1) { 792 string pkg; 793 pkg.assign(args[1].c_str(), args[1].size()); 794 auto uids = mUidMap->getAppUid(pkg); 795 dprintf(out, "%s -> [ ", pkg.c_str()); 796 for (const auto& uid : uids) { 797 dprintf(out, "%d ", uid); 798 } 799 dprintf(out, "]\n"); 800 } else { 801 mUidMap->printUidMap(out); 802 } 803 return NO_ERROR; 804 } 805 806 status_t StatsService::cmd_write_data_to_disk(int out) { 807 dprintf(out, "Writing data to disk\n"); 808 mProcessor->WriteDataToDisk(ADB_DUMP, NO_TIME_CONSTRAINTS); 809 return NO_ERROR; 810 } 811 812 status_t StatsService::cmd_log_app_breadcrumb(int out, const Vector<String8>& args) { 813 bool good = false; 814 int32_t uid; 815 int32_t label; 816 int32_t state; 817 const int argCount = args.size(); 818 if (argCount == 3) { 819 // Automatically pick the UID 820 uid = IPCThreadState::self()->getCallingUid(); 821 label = atoi(args[1].c_str()); 822 state = atoi(args[2].c_str()); 823 good = true; 824 } else if (argCount == 4) { 825 good = getUidFromArgs(args, 1, uid); 826 if (!good) { 827 dprintf(out, 828 "Invalid UID. Note that selecting a UID for writing AppBreadcrumb can only be " 829 "done for other UIDs on eng or userdebug builds.\n"); 830 } 831 label = atoi(args[2].c_str()); 832 state = atoi(args[3].c_str()); 833 } 834 if (good) { 835 dprintf(out, "Logging AppBreadcrumbReported(%d, %d, %d) to statslog.\n", uid, label, state); 836 android::util::stats_write(android::util::APP_BREADCRUMB_REPORTED, uid, label, state); 837 } else { 838 print_cmd_help(out); 839 return UNKNOWN_ERROR; 840 } 841 return NO_ERROR; 842 } 843 844 status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args) { 845 // Security checks are done in the sendBinaryPushStateChanged atom. 846 const int argCount = args.size(); 847 if (argCount != 7 && argCount != 8) { 848 dprintf(out, "Incorrect number of argument supplied\n"); 849 return UNKNOWN_ERROR; 850 } 851 android::String16 trainName = android::String16(args[1].c_str()); 852 int64_t trainVersion = strtoll(args[2].c_str(), nullptr, 10); 853 int options = 0; 854 if (args[3] == "1") { 855 options = options | IStatsManager::FLAG_REQUIRE_STAGING; 856 } 857 if (args[4] == "1") { 858 options = options | IStatsManager::FLAG_ROLLBACK_ENABLED; 859 } 860 if (args[5] == "1") { 861 options = options | IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR; 862 } 863 int32_t state = atoi(args[6].c_str()); 864 vector<int64_t> experimentIds; 865 if (argCount == 8) { 866 vector<string> experimentIdsString = android::base::Split(string(args[7].c_str()), ","); 867 for (string experimentIdString : experimentIdsString) { 868 int64_t experimentId = strtoll(experimentIdString.c_str(), nullptr, 10); 869 experimentIds.push_back(experimentId); 870 } 871 } 872 dprintf(out, "Logging BinaryPushStateChanged\n"); 873 sendBinaryPushStateChangedAtom(trainName, trainVersion, options, state, experimentIds); 874 return NO_ERROR; 875 } 876 877 status_t StatsService::cmd_print_pulled_metrics(int out, const Vector<String8>& args) { 878 int s = atoi(args[1].c_str()); 879 vector<shared_ptr<LogEvent> > stats; 880 if (mPullerManager->Pull(s, &stats)) { 881 for (const auto& it : stats) { 882 dprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str()); 883 } 884 dprintf(out, "Pull from %d: Received %zu elements\n", s, stats.size()); 885 return NO_ERROR; 886 } 887 return UNKNOWN_ERROR; 888 } 889 890 status_t StatsService::cmd_remove_all_configs(int out) { 891 dprintf(out, "Removing all configs...\n"); 892 VLOG("StatsService::cmd_remove_all_configs was called"); 893 mConfigManager->RemoveAllConfigs(); 894 StorageManager::deleteAllFiles(STATS_SERVICE_DIR); 895 return NO_ERROR; 896 } 897 898 status_t StatsService::cmd_dump_memory_info(int out) { 899 dprintf(out, "meminfo not available.\n"); 900 return NO_ERROR; 901 } 902 903 status_t StatsService::cmd_clear_puller_cache(int out) { 904 IPCThreadState* ipc = IPCThreadState::self(); 905 VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i", 906 ipc->getCallingPid(), ipc->getCallingUid()); 907 if (checkCallingPermission(String16(kPermissionDump))) { 908 int cleared = mPullerManager->ForceClearPullerCache(); 909 dprintf(out, "Puller removed %d cached data!\n", cleared); 910 return NO_ERROR; 911 } else { 912 return PERMISSION_DENIED; 913 } 914 } 915 916 status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) { 917 IPCThreadState* ipc = IPCThreadState::self(); 918 VLOG("StatsService::cmd_print_logs with Pid %i, Uid %i", ipc->getCallingPid(), 919 ipc->getCallingUid()); 920 if (checkCallingPermission(String16(kPermissionDump))) { 921 bool enabled = true; 922 if (args.size() >= 2) { 923 enabled = atoi(args[1].c_str()) != 0; 924 } 925 mProcessor->setPrintLogs(enabled); 926 return NO_ERROR; 927 } else { 928 return PERMISSION_DENIED; 929 } 930 } 931 932 bool StatsService::getUidFromArgs(const Vector<String8>& args, size_t uidArgIndex, int32_t& uid) { 933 return getUidFromString(args[uidArgIndex].c_str(), uid); 934 } 935 936 bool StatsService::getUidFromString(const char* s, int32_t& uid) { 937 if (*s == '\0') { 938 return false; 939 } 940 char* endc = NULL; 941 int64_t longUid = strtol(s, &endc, 0); 942 if (*endc != '\0') { 943 return false; 944 } 945 int32_t goodUid = static_cast<int32_t>(longUid); 946 if (longUid < 0 || static_cast<uint64_t>(longUid) != static_cast<uid_t>(goodUid)) { 947 return false; // It was not of uid_t type. 948 } 949 uid = goodUid; 950 951 int32_t callingUid = IPCThreadState::self()->getCallingUid(); 952 return mEngBuild // UserDebug/EngBuild are allowed to impersonate uids. 953 || (callingUid == goodUid) // Anyone can 'impersonate' themselves. 954 || (callingUid == AID_ROOT && goodUid == AID_SHELL); // ROOT can impersonate SHELL. 955 } 956 957 Status StatsService::informAllUidData(const ParcelFileDescriptor& fd) { 958 ENFORCE_UID(AID_SYSTEM); 959 // Read stream into buffer. 960 string buffer; 961 if (!android::base::ReadFdToString(fd.get(), &buffer)) { 962 return exception(Status::EX_ILLEGAL_ARGUMENT, "Failed to read all data from the pipe."); 963 } 964 965 // Parse buffer. 966 UidData uidData; 967 if (!uidData.ParseFromString(buffer)) { 968 return exception(Status::EX_ILLEGAL_ARGUMENT, "Error parsing proto stream for UidData."); 969 } 970 971 vector<String16> versionStrings; 972 vector<String16> installers; 973 vector<String16> packageNames; 974 vector<int32_t> uids; 975 vector<int64_t> versions; 976 977 const auto numEntries = uidData.app_info_size(); 978 versionStrings.reserve(numEntries); 979 installers.reserve(numEntries); 980 packageNames.reserve(numEntries); 981 uids.reserve(numEntries); 982 versions.reserve(numEntries); 983 984 for (const auto& appInfo: uidData.app_info()) { 985 packageNames.emplace_back(String16(appInfo.package_name().c_str())); 986 uids.push_back(appInfo.uid()); 987 versions.push_back(appInfo.version()); 988 versionStrings.emplace_back(String16(appInfo.version_string().c_str())); 989 installers.emplace_back(String16(appInfo.installer().c_str())); 990 } 991 992 mUidMap->updateMap(getElapsedRealtimeNs(), 993 uids, 994 versions, 995 versionStrings, 996 packageNames, 997 installers); 998 999 VLOG("StatsService::informAllUidData UidData proto parsed successfully."); 1000 return Status::ok(); 1001 } 1002 1003 Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version, 1004 const String16& version_string, const String16& installer) { 1005 ENFORCE_UID(AID_SYSTEM); 1006 1007 VLOG("StatsService::informOnePackage was called"); 1008 mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version, version_string, installer); 1009 return Status::ok(); 1010 } 1011 1012 Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) { 1013 ENFORCE_UID(AID_SYSTEM); 1014 1015 VLOG("StatsService::informOnePackageRemoved was called"); 1016 mUidMap->removeApp(getElapsedRealtimeNs(), app, uid); 1017 mConfigManager->RemoveConfigs(uid); 1018 return Status::ok(); 1019 } 1020 1021 Status StatsService::informAnomalyAlarmFired() { 1022 ENFORCE_UID(AID_SYSTEM); 1023 1024 VLOG("StatsService::informAnomalyAlarmFired was called"); 1025 int64_t currentTimeSec = getElapsedRealtimeSec(); 1026 std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet = 1027 mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); 1028 if (alarmSet.size() > 0) { 1029 VLOG("Found an anomaly alarm that fired."); 1030 mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet); 1031 } else { 1032 VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled."); 1033 } 1034 return Status::ok(); 1035 } 1036 1037 Status StatsService::informAlarmForSubscriberTriggeringFired() { 1038 ENFORCE_UID(AID_SYSTEM); 1039 1040 VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); 1041 int64_t currentTimeSec = getElapsedRealtimeSec(); 1042 std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet = 1043 mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec)); 1044 if (alarmSet.size() > 0) { 1045 VLOG("Found periodic alarm fired."); 1046 mProcessor->onPeriodicAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet); 1047 } else { 1048 ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled."); 1049 } 1050 return Status::ok(); 1051 } 1052 1053 Status StatsService::informPollAlarmFired() { 1054 ENFORCE_UID(AID_SYSTEM); 1055 1056 VLOG("StatsService::informPollAlarmFired was called"); 1057 mProcessor->informPullAlarmFired(getElapsedRealtimeNs()); 1058 VLOG("StatsService::informPollAlarmFired succeeded"); 1059 return Status::ok(); 1060 } 1061 1062 Status StatsService::systemRunning() { 1063 ENFORCE_UID(AID_SYSTEM); 1064 1065 // When system_server is up and running, schedule the dropbox task to run. 1066 VLOG("StatsService::systemRunning"); 1067 sayHiToStatsCompanion(); 1068 return Status::ok(); 1069 } 1070 1071 Status StatsService::informDeviceShutdown() { 1072 ENFORCE_UID(AID_SYSTEM); 1073 VLOG("StatsService::informDeviceShutdown"); 1074 mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST); 1075 mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); 1076 return Status::ok(); 1077 } 1078 1079 void StatsService::sayHiToStatsCompanion() { 1080 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService(); 1081 if (statsCompanion != nullptr) { 1082 VLOG("Telling statsCompanion that statsd is ready"); 1083 statsCompanion->statsdReady(); 1084 } else { 1085 VLOG("Could not access statsCompanion"); 1086 } 1087 } 1088 1089 Status StatsService::statsCompanionReady() { 1090 ENFORCE_UID(AID_SYSTEM); 1091 1092 VLOG("StatsService::statsCompanionReady was called"); 1093 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService(); 1094 if (statsCompanion == nullptr) { 1095 return Status::fromExceptionCode( 1096 Status::EX_NULL_POINTER, 1097 "statscompanion unavailable despite it contacting statsd!"); 1098 } 1099 VLOG("StatsService::statsCompanionReady linking to statsCompanion."); 1100 IInterface::asBinder(statsCompanion)->linkToDeath(this); 1101 mPullerManager->SetStatsCompanionService(statsCompanion); 1102 mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion); 1103 mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion); 1104 SubscriberReporter::getInstance().setStatsCompanionService(statsCompanion); 1105 return Status::ok(); 1106 } 1107 1108 void StatsService::Startup() { 1109 mConfigManager->Startup(); 1110 mProcessor->LoadActiveConfigsFromDisk(); 1111 } 1112 1113 void StatsService::Terminate() { 1114 ALOGI("StatsService::Terminating"); 1115 if (mProcessor != nullptr) { 1116 mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST); 1117 mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs()); 1118 } 1119 } 1120 1121 // Test only interface!!! 1122 void StatsService::OnLogEvent(LogEvent* event) { 1123 mProcessor->OnLogEvent(event); 1124 if (mShellSubscriber != nullptr) { 1125 mShellSubscriber->onLogEvent(*event); 1126 } 1127 } 1128 1129 Status StatsService::getData(int64_t key, const String16& packageName, vector<uint8_t>* output) { 1130 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1131 1132 IPCThreadState* ipc = IPCThreadState::self(); 1133 VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); 1134 ConfigKey configKey(ipc->getCallingUid(), key); 1135 // The dump latency does not matter here since we do not include the current bucket, we do not 1136 // need to pull any new data anyhow. 1137 mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/, 1138 true /* erase_data */, GET_DATA_CALLED, FAST, output); 1139 return Status::ok(); 1140 } 1141 1142 Status StatsService::getMetadata(const String16& packageName, vector<uint8_t>* output) { 1143 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1144 1145 IPCThreadState* ipc = IPCThreadState::self(); 1146 VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(), 1147 ipc->getCallingUid()); 1148 StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters. 1149 return Status::ok(); 1150 } 1151 1152 Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config, 1153 const String16& packageName) { 1154 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1155 1156 IPCThreadState* ipc = IPCThreadState::self(); 1157 if (addConfigurationChecked(ipc->getCallingUid(), key, config)) { 1158 return Status::ok(); 1159 } else { 1160 ALOGE("Could not parse malformatted StatsdConfig"); 1161 return Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT, 1162 "config does not correspond to a StatsdConfig proto"); 1163 } 1164 } 1165 1166 bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<uint8_t>& config) { 1167 ConfigKey configKey(uid, key); 1168 StatsdConfig cfg; 1169 if (config.size() > 0) { // If the config is empty, skip parsing. 1170 if (!cfg.ParseFromArray(&config[0], config.size())) { 1171 return false; 1172 } 1173 } 1174 mConfigManager->UpdateConfig(configKey, cfg); 1175 return true; 1176 } 1177 1178 Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) { 1179 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1180 1181 IPCThreadState* ipc = IPCThreadState::self(); 1182 ConfigKey configKey(ipc->getCallingUid(), key); 1183 mConfigManager->RemoveConfigReceiver(configKey); 1184 return Status::ok(); 1185 } 1186 1187 Status StatsService::setDataFetchOperation(int64_t key, 1188 const sp<android::IBinder>& intentSender, 1189 const String16& packageName) { 1190 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1191 1192 IPCThreadState* ipc = IPCThreadState::self(); 1193 ConfigKey configKey(ipc->getCallingUid(), key); 1194 mConfigManager->SetConfigReceiver(configKey, intentSender); 1195 if (StorageManager::hasConfigMetricsReport(configKey)) { 1196 VLOG("StatsService::setDataFetchOperation marking configKey %s to dump reports on disk", 1197 configKey.ToString().c_str()); 1198 mProcessor->noteOnDiskData(configKey); 1199 } 1200 return Status::ok(); 1201 } 1202 1203 Status StatsService::setActiveConfigsChangedOperation(const sp<android::IBinder>& intentSender, 1204 const String16& packageName, 1205 vector<int64_t>* output) { 1206 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1207 1208 IPCThreadState* ipc = IPCThreadState::self(); 1209 int uid = ipc->getCallingUid(); 1210 mConfigManager->SetActiveConfigsChangedReceiver(uid, intentSender); 1211 if (output != nullptr) { 1212 mProcessor->GetActiveConfigs(uid, *output); 1213 } else { 1214 ALOGW("StatsService::setActiveConfigsChanged output was nullptr"); 1215 } 1216 return Status::ok(); 1217 } 1218 1219 Status StatsService::removeActiveConfigsChangedOperation(const String16& packageName) { 1220 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1221 1222 IPCThreadState* ipc = IPCThreadState::self(); 1223 mConfigManager->RemoveActiveConfigsChangedReceiver(ipc->getCallingUid()); 1224 return Status::ok(); 1225 } 1226 1227 Status StatsService::removeConfiguration(int64_t key, const String16& packageName) { 1228 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1229 1230 IPCThreadState* ipc = IPCThreadState::self(); 1231 ConfigKey configKey(ipc->getCallingUid(), key); 1232 mConfigManager->RemoveConfig(configKey); 1233 SubscriberReporter::getInstance().removeConfig(configKey); 1234 return Status::ok(); 1235 } 1236 1237 Status StatsService::setBroadcastSubscriber(int64_t configId, 1238 int64_t subscriberId, 1239 const sp<android::IBinder>& intentSender, 1240 const String16& packageName) { 1241 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1242 1243 VLOG("StatsService::setBroadcastSubscriber called."); 1244 IPCThreadState* ipc = IPCThreadState::self(); 1245 ConfigKey configKey(ipc->getCallingUid(), configId); 1246 SubscriberReporter::getInstance() 1247 .setBroadcastSubscriber(configKey, subscriberId, intentSender); 1248 return Status::ok(); 1249 } 1250 1251 Status StatsService::unsetBroadcastSubscriber(int64_t configId, 1252 int64_t subscriberId, 1253 const String16& packageName) { 1254 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1255 1256 VLOG("StatsService::unsetBroadcastSubscriber called."); 1257 IPCThreadState* ipc = IPCThreadState::self(); 1258 ConfigKey configKey(ipc->getCallingUid(), configId); 1259 SubscriberReporter::getInstance() 1260 .unsetBroadcastSubscriber(configKey, subscriberId); 1261 return Status::ok(); 1262 } 1263 1264 Status StatsService::sendAppBreadcrumbAtom(int32_t label, int32_t state) { 1265 // Permission check not necessary as it's meant for applications to write to 1266 // statsd. 1267 android::util::stats_write(util::APP_BREADCRUMB_REPORTED, 1268 IPCThreadState::self()->getCallingUid(), label, 1269 state); 1270 return Status::ok(); 1271 } 1272 1273 Status StatsService::registerPullerCallback(int32_t atomTag, 1274 const sp<android::os::IStatsPullerCallback>& pullerCallback, 1275 const String16& packageName) { 1276 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1277 1278 VLOG("StatsService::registerPullerCallback called."); 1279 mPullerManager->RegisterPullerCallback(atomTag, pullerCallback); 1280 return Status::ok(); 1281 } 1282 1283 Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& packageName) { 1284 ENFORCE_DUMP_AND_USAGE_STATS(packageName); 1285 1286 VLOG("StatsService::unregisterPullerCallback called."); 1287 mPullerManager->UnregisterPullerCallback(atomTag); 1288 return Status::ok(); 1289 } 1290 1291 Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& trainNameIn, 1292 const int64_t trainVersionCodeIn, 1293 const int options, 1294 const int32_t state, 1295 const std::vector<int64_t>& experimentIdsIn) { 1296 // Note: We skip the usage stats op check here since we do not have a package name. 1297 // This is ok since we are overloading the usage_stats permission. 1298 // This method only sends data, it does not receive it. 1299 pid_t pid = IPCThreadState::self()->getCallingPid(); 1300 uid_t uid = IPCThreadState::self()->getCallingUid(); 1301 // Root, system, and shell always have access 1302 if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) { 1303 // Caller must be granted these permissions 1304 if (!checkCallingPermission(String16(kPermissionDump))) { 1305 return exception(binder::Status::EX_SECURITY, 1306 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, 1307 kPermissionDump)); 1308 } 1309 if (!checkCallingPermission(String16(kPermissionUsage))) { 1310 return exception(binder::Status::EX_SECURITY, 1311 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, 1312 kPermissionUsage)); 1313 } 1314 } 1315 1316 bool readTrainInfoSuccess = false; 1317 InstallTrainInfo trainInfoOnDisk; 1318 readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk); 1319 1320 bool resetExperimentIds = false; 1321 int64_t trainVersionCode = trainVersionCodeIn; 1322 std::string trainNameUtf8 = std::string(String8(trainNameIn).string()); 1323 if (readTrainInfoSuccess) { 1324 // Keep the old train version if we received an empty version. 1325 if (trainVersionCodeIn == -1) { 1326 trainVersionCode = trainInfoOnDisk.trainVersionCode; 1327 } else if (trainVersionCodeIn != trainInfoOnDisk.trainVersionCode) { 1328 // Reset experiment ids if we receive a new non-empty train version. 1329 resetExperimentIds = true; 1330 } 1331 1332 // Keep the old train name if we received an empty train name. 1333 if (trainNameUtf8.size() == 0) { 1334 trainNameUtf8 = trainInfoOnDisk.trainName; 1335 } else if (trainNameUtf8 != trainInfoOnDisk.trainName) { 1336 // Reset experiment ids if we received a new valid train name. 1337 resetExperimentIds = true; 1338 } 1339 1340 // Reset if we received a different experiment id. 1341 if (!experimentIdsIn.empty() && 1342 (trainInfoOnDisk.experimentIds.empty() || 1343 experimentIdsIn[0] != trainInfoOnDisk.experimentIds[0])) { 1344 resetExperimentIds = true; 1345 } 1346 } 1347 1348 // Find the right experiment IDs 1349 std::vector<int64_t> experimentIds; 1350 if (resetExperimentIds || !readTrainInfoSuccess) { 1351 experimentIds = experimentIdsIn; 1352 } else { 1353 experimentIds = trainInfoOnDisk.experimentIds; 1354 } 1355 1356 if (!experimentIds.empty()) { 1357 int64_t firstId = experimentIds[0]; 1358 switch (state) { 1359 case android::util::BINARY_PUSH_STATE_CHANGED__STATE__INSTALL_SUCCESS: 1360 experimentIds.push_back(firstId + 1); 1361 break; 1362 case android::util::BINARY_PUSH_STATE_CHANGED__STATE__INSTALLER_ROLLBACK_INITIATED: 1363 experimentIds.push_back(firstId + 2); 1364 break; 1365 case android::util::BINARY_PUSH_STATE_CHANGED__STATE__INSTALLER_ROLLBACK_SUCCESS: 1366 experimentIds.push_back(firstId + 3); 1367 break; 1368 } 1369 } 1370 1371 // Flatten the experiment IDs to proto 1372 vector<uint8_t> experimentIdsProtoBuffer; 1373 writeExperimentIdsToProto(experimentIds, &experimentIdsProtoBuffer); 1374 StorageManager::writeTrainInfo(trainVersionCode, trainNameUtf8, state, experimentIds); 1375 1376 userid_t userId = multiuser_get_user_id(uid); 1377 bool requiresStaging = options & IStatsManager::FLAG_REQUIRE_STAGING; 1378 bool rollbackEnabled = options & IStatsManager::FLAG_ROLLBACK_ENABLED; 1379 bool requiresLowLatencyMonitor = options & IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR; 1380 LogEvent event(trainNameUtf8, trainVersionCode, requiresStaging, rollbackEnabled, 1381 requiresLowLatencyMonitor, state, experimentIdsProtoBuffer, userId); 1382 mProcessor->OnLogEvent(&event); 1383 return Status::ok(); 1384 } 1385 1386 Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn, 1387 const android::String16& packageNameIn, 1388 const int64_t packageVersionCodeIn) { 1389 // Note: We skip the usage stats op check here since we do not have a package name. 1390 // This is ok since we are overloading the usage_stats permission. 1391 // This method only sends data, it does not receive it. 1392 pid_t pid = IPCThreadState::self()->getCallingPid(); 1393 uid_t uid = IPCThreadState::self()->getCallingUid(); 1394 // Root, system, and shell always have access 1395 if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) { 1396 // Caller must be granted these permissions 1397 if (!checkCallingPermission(String16(kPermissionDump))) { 1398 return exception(binder::Status::EX_SECURITY, 1399 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, 1400 kPermissionDump)); 1401 } 1402 if (!checkCallingPermission(String16(kPermissionUsage))) { 1403 return exception(binder::Status::EX_SECURITY, 1404 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, 1405 kPermissionUsage)); 1406 } 1407 } 1408 1409 android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED, 1410 rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn); 1411 1412 // Fast return to save disk read. 1413 if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS 1414 && rollbackTypeIn != 1415 android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE) { 1416 return Status::ok(); 1417 } 1418 1419 bool readTrainInfoSuccess = false; 1420 InstallTrainInfo trainInfoOnDisk; 1421 readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk); 1422 1423 if (!readTrainInfoSuccess) { 1424 return Status::ok(); 1425 } 1426 std::vector<int64_t> experimentIds = trainInfoOnDisk.experimentIds; 1427 if (experimentIds.empty()) { 1428 return Status::ok(); 1429 } 1430 switch (rollbackTypeIn) { 1431 case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE: 1432 experimentIds.push_back(experimentIds[0] + 4); 1433 break; 1434 case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS: 1435 experimentIds.push_back(experimentIds[0] + 5); 1436 break; 1437 } 1438 StorageManager::writeTrainInfo(trainInfoOnDisk.trainVersionCode, trainInfoOnDisk.trainName, 1439 trainInfoOnDisk.status, experimentIds); 1440 return Status::ok(); 1441 } 1442 1443 1444 Status StatsService::getRegisteredExperimentIds(std::vector<int64_t>* experimentIdsOut) { 1445 uid_t uid = IPCThreadState::self()->getCallingUid(); 1446 1447 // Caller must be granted these permissions 1448 if (!checkCallingPermission(String16(kPermissionDump))) { 1449 return exception(binder::Status::EX_SECURITY, 1450 StringPrintf("UID %d lacks permission %s", uid, kPermissionDump)); 1451 } 1452 if (!checkCallingPermission(String16(kPermissionUsage))) { 1453 return exception(binder::Status::EX_SECURITY, 1454 StringPrintf("UID %d lacks permission %s", uid, kPermissionUsage)); 1455 } 1456 // TODO: add verifier permission 1457 1458 // Read the latest train info 1459 InstallTrainInfo trainInfo; 1460 if (!StorageManager::readTrainInfo(trainInfo)) { 1461 // No train info means no experiment IDs, return an empty list 1462 experimentIdsOut->clear(); 1463 return Status::ok(); 1464 } 1465 1466 // Copy the experiment IDs to the out vector 1467 experimentIdsOut->assign(trainInfo.experimentIds.begin(), trainInfo.experimentIds.end()); 1468 return Status::ok(); 1469 } 1470 1471 hardware::Return<void> StatsService::reportSpeakerImpedance( 1472 const SpeakerImpedance& speakerImpedance) { 1473 android::util::stats_write(android::util::SPEAKER_IMPEDANCE_REPORTED, 1474 speakerImpedance.speakerLocation, speakerImpedance.milliOhms); 1475 1476 return hardware::Void(); 1477 } 1478 1479 hardware::Return<void> StatsService::reportHardwareFailed(const HardwareFailed& hardwareFailed) { 1480 android::util::stats_write(android::util::HARDWARE_FAILED, int32_t(hardwareFailed.hardwareType), 1481 hardwareFailed.hardwareLocation, int32_t(hardwareFailed.errorCode)); 1482 1483 return hardware::Void(); 1484 } 1485 1486 hardware::Return<void> StatsService::reportPhysicalDropDetected( 1487 const PhysicalDropDetected& physicalDropDetected) { 1488 android::util::stats_write(android::util::PHYSICAL_DROP_DETECTED, 1489 int32_t(physicalDropDetected.confidencePctg), physicalDropDetected.accelPeak, 1490 physicalDropDetected.freefallDuration); 1491 1492 return hardware::Void(); 1493 } 1494 1495 hardware::Return<void> StatsService::reportChargeCycles(const ChargeCycles& chargeCycles) { 1496 std::vector<int32_t> buckets = chargeCycles.cycleBucket; 1497 int initialSize = buckets.size(); 1498 for (int i = 0; i < 10 - initialSize; i++) { 1499 buckets.push_back(-1); // Push -1 for buckets that do not exist. 1500 } 1501 android::util::stats_write(android::util::CHARGE_CYCLES_REPORTED, buckets[0], buckets[1], 1502 buckets[2], buckets[3], buckets[4], buckets[5], buckets[6], buckets[7], buckets[8], 1503 buckets[9]); 1504 1505 return hardware::Void(); 1506 } 1507 1508 hardware::Return<void> StatsService::reportBatteryHealthSnapshot( 1509 const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) { 1510 android::util::stats_write(android::util::BATTERY_HEALTH_SNAPSHOT, 1511 int32_t(batteryHealthSnapshotArgs.type), batteryHealthSnapshotArgs.temperatureDeciC, 1512 batteryHealthSnapshotArgs.voltageMicroV, batteryHealthSnapshotArgs.currentMicroA, 1513 batteryHealthSnapshotArgs.openCircuitVoltageMicroV, 1514 batteryHealthSnapshotArgs.resistanceMicroOhm, batteryHealthSnapshotArgs.levelPercent); 1515 1516 return hardware::Void(); 1517 } 1518 1519 hardware::Return<void> StatsService::reportSlowIo(const SlowIo& slowIo) { 1520 android::util::stats_write(android::util::SLOW_IO, int32_t(slowIo.operation), slowIo.count); 1521 1522 return hardware::Void(); 1523 } 1524 1525 hardware::Return<void> StatsService::reportBatteryCausedShutdown( 1526 const BatteryCausedShutdown& batteryCausedShutdown) { 1527 android::util::stats_write(android::util::BATTERY_CAUSED_SHUTDOWN, 1528 batteryCausedShutdown.voltageMicroV); 1529 1530 return hardware::Void(); 1531 } 1532 1533 hardware::Return<void> StatsService::reportUsbPortOverheatEvent( 1534 const UsbPortOverheatEvent& usbPortOverheatEvent) { 1535 android::util::stats_write(android::util::USB_PORT_OVERHEAT_EVENT_REPORTED, 1536 usbPortOverheatEvent.plugTemperatureDeciC, usbPortOverheatEvent.maxTemperatureDeciC, 1537 usbPortOverheatEvent.timeToOverheat, usbPortOverheatEvent.timeToHysteresis, 1538 usbPortOverheatEvent.timeToInactive); 1539 1540 return hardware::Void(); 1541 } 1542 1543 hardware::Return<void> StatsService::reportSpeechDspStat( 1544 const SpeechDspStat& speechDspStat) { 1545 android::util::stats_write(android::util::SPEECH_DSP_STAT_REPORTED, 1546 speechDspStat.totalUptimeMillis, speechDspStat.totalDowntimeMillis, 1547 speechDspStat.totalCrashCount, speechDspStat.totalRecoverCount); 1548 1549 return hardware::Void(); 1550 } 1551 1552 hardware::Return<void> StatsService::reportVendorAtom(const VendorAtom& vendorAtom) { 1553 std::string reverseDomainName = (std::string) vendorAtom.reverseDomainName; 1554 if (vendorAtom.atomId < 100000 || vendorAtom.atomId >= 200000) { 1555 ALOGE("Atom ID %ld is not a valid vendor atom ID", (long) vendorAtom.atomId); 1556 return hardware::Void(); 1557 } 1558 if (reverseDomainName.length() > 50) { 1559 ALOGE("Vendor atom reverse domain name %s is too long.", reverseDomainName.c_str()); 1560 return hardware::Void(); 1561 } 1562 LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), vendorAtom); 1563 mProcessor->OnLogEvent(&event); 1564 1565 return hardware::Void(); 1566 } 1567 1568 void StatsService::binderDied(const wp <IBinder>& who) { 1569 ALOGW("statscompanion service died"); 1570 StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec()); 1571 if (mProcessor != nullptr) { 1572 ALOGW("Reset statsd upon system server restarts."); 1573 int64_t systemServerRestartNs = getElapsedRealtimeNs(); 1574 ProtoOutputStream proto; 1575 mProcessor->WriteActiveConfigsToProtoOutputStream(systemServerRestartNs, 1576 STATSCOMPANION_DIED, &proto); 1577 1578 mProcessor->WriteDataToDisk(STATSCOMPANION_DIED, FAST); 1579 mProcessor->resetConfigs(); 1580 1581 std::string serializedActiveConfigs; 1582 if (proto.serializeToString(&serializedActiveConfigs)) { 1583 ActiveConfigList activeConfigs; 1584 if (activeConfigs.ParseFromString(serializedActiveConfigs)) { 1585 mProcessor->SetConfigsActiveState(activeConfigs, systemServerRestartNs); 1586 } 1587 } 1588 } 1589 mAnomalyAlarmMonitor->setStatsCompanionService(nullptr); 1590 mPeriodicAlarmMonitor->setStatsCompanionService(nullptr); 1591 SubscriberReporter::getInstance().setStatsCompanionService(nullptr); 1592 mPullerManager->SetStatsCompanionService(nullptr); 1593 } 1594 1595 } // namespace statsd 1596 } // namespace os 1597 } // namespace android 1598