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/strings.h>
31 #include <cutils/multiuser.h>
32 #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
33 #include <frameworks/base/cmds/statsd/src/uid_data.pb.h>
34 #include <private/android_filesystem_config.h>
35 #include <statslog_statsd.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <sys/system_properties.h>
39 #include <unistd.h>
40 #include <utils/String16.h>
41
42 using namespace android;
43
44 using android::base::StringPrintf;
45 using android::util::FIELD_COUNT_REPEATED;
46 using android::util::FIELD_TYPE_MESSAGE;
47
48 using Status = ::ndk::ScopedAStatus;
49
50 namespace android {
51 namespace os {
52 namespace statsd {
53
54 constexpr const char* kPermissionDump = "android.permission.DUMP";
55
56 constexpr const char* kPermissionRegisterPullAtom = "android.permission.REGISTER_STATS_PULL_ATOM";
57
58 #define STATS_SERVICE_DIR "/data/misc/stats-service"
59
60 // for StatsDataDumpProto
61 const int FIELD_ID_REPORTS_LIST = 1;
62
exception(int32_t code,const std::string & msg)63 static Status exception(int32_t code, const std::string& msg) {
64 ALOGE("%s (%d)", msg.c_str(), code);
65 return Status::fromExceptionCodeWithMessage(code, msg.c_str());
66 }
67
checkPermission(const char * permission)68 static bool checkPermission(const char* permission) {
69 pid_t pid = AIBinder_getCallingPid();
70 uid_t uid = AIBinder_getCallingUid();
71 return checkPermissionForIds(permission, pid, uid);
72 }
73
checkUid(uid_t expectedUid)74 Status checkUid(uid_t expectedUid) {
75 uid_t uid = AIBinder_getCallingUid();
76 if (uid == expectedUid || uid == AID_ROOT) {
77 return Status::ok();
78 } else {
79 return exception(EX_SECURITY,
80 StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
81 }
82 }
83
84 #define ENFORCE_UID(uid) { \
85 Status status = checkUid((uid)); \
86 if (!status.isOk()) { \
87 return status; \
88 } \
89 }
90
StatsService(const sp<Looper> & handlerLooper,shared_ptr<LogEventQueue> queue)91 StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue)
92 : mAnomalyAlarmMonitor(new AlarmMonitor(
93 MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
94 [](const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) {
95 if (sc != nullptr) {
96 sc->setAnomalyAlarm(timeMillis);
97 StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
98 }
99 },
__anon24fc2e590202(const shared_ptr<IStatsCompanionService>& sc) 100 [](const shared_ptr<IStatsCompanionService>& sc) {
101 if (sc != nullptr) {
102 sc->cancelAnomalyAlarm();
103 StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
104 }
105 })),
106 mPeriodicAlarmMonitor(new AlarmMonitor(
107 MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
__anon24fc2e590302(const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) 108 [](const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) {
109 if (sc != nullptr) {
110 sc->setAlarmForSubscriberTriggering(timeMillis);
111 StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged();
112 }
113 },
__anon24fc2e590402(const shared_ptr<IStatsCompanionService>& sc) 114 [](const shared_ptr<IStatsCompanionService>& sc) {
115 if (sc != nullptr) {
116 sc->cancelAlarmForSubscriberTriggering();
117 StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged();
118 }
119 })),
120 mEventQueue(queue),
121 mBootCompleteTrigger({kBootCompleteTag, kUidMapReceivedTag, kAllPullersRegisteredTag},
__anon24fc2e590502() 122 [this]() { mProcessor->onStatsdInitCompleted(getElapsedRealtimeNs()); }),
123 mStatsCompanionServiceDeathRecipient(
124 AIBinder_DeathRecipient_new(StatsService::statsCompanionServiceDied)) {
125 mUidMap = UidMap::getInstance();
126 mPullerManager = new StatsPullerManager();
127 StatsPuller::SetUidMap(mUidMap);
128 mConfigManager = new ConfigManager();
129 mProcessor = new StatsLogProcessor(
130 mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
131 getElapsedRealtimeNs(),
__anon24fc2e590602(const ConfigKey& key) 132 [this](const ConfigKey& key) {
133 shared_ptr<IPendingIntentRef> receiver = mConfigManager->GetConfigReceiver(key);
134 if (receiver == nullptr) {
135 VLOG("Could not find a broadcast receiver for %s", key.ToString().c_str());
136 return false;
137 } else if (receiver->sendDataBroadcast(
138 mProcessor->getLastReportTimeNs(key)).isOk()) {
139 return true;
140 } else {
141 VLOG("Failed to send a broadcast for receiver %s", key.ToString().c_str());
142 return false;
143 }
144 },
__anon24fc2e590702(const int& uid, const vector<int64_t>& activeConfigs) 145 [this](const int& uid, const vector<int64_t>& activeConfigs) {
146 shared_ptr<IPendingIntentRef> receiver =
147 mConfigManager->GetActiveConfigsChangedReceiver(uid);
148 if (receiver == nullptr) {
149 VLOG("Could not find receiver for uid %d", uid);
150 return false;
151 } else if (receiver->sendActiveConfigsChangedBroadcast(activeConfigs).isOk()) {
152 VLOG("StatsService::active configs broadcast succeeded for uid %d" , uid);
153 return true;
154 } else {
155 VLOG("StatsService::active configs broadcast failed for uid %d" , uid);
156 return false;
157 }
158 });
159
160 mUidMap->setListener(mProcessor);
161 mConfigManager->AddListener(mProcessor);
162
163 init_system_properties();
164
165 if (mEventQueue != nullptr) {
__anon24fc2e590802null166 std::thread pushedEventThread([this] { readLogs(); });
167 pushedEventThread.detach();
168 }
169 }
170
~StatsService()171 StatsService::~StatsService() {
172 }
173
174 /* Runs on a dedicated thread to process pushed events. */
readLogs()175 void StatsService::readLogs() {
176 // Read forever..... long live statsd
177 while (1) {
178 // Block until an event is available.
179 auto event = mEventQueue->waitPop();
180 // Pass it to StatsLogProcess to all configs/metrics
181 // At this point, the LogEventQueue is not blocked, so that the socketListener
182 // can read events from the socket and write to buffer to avoid data drop.
183 mProcessor->OnLogEvent(event.get());
184 // The ShellSubscriber is only used by shell for local debugging.
185 if (mShellSubscriber != nullptr) {
186 mShellSubscriber->onLogEvent(*event);
187 }
188 }
189 }
190
init_system_properties()191 void StatsService::init_system_properties() {
192 mEngBuild = false;
193 const prop_info* buildType = __system_property_find("ro.build.type");
194 if (buildType != NULL) {
195 __system_property_read_callback(buildType, init_build_type_callback, this);
196 }
197 }
198
init_build_type_callback(void * cookie,const char *,const char * value,uint32_t serial)199 void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
200 uint32_t serial) {
201 if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) {
202 reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
203 }
204 }
205
206 /**
207 * Write data from statsd.
208 * Format for statsdStats: adb shell dumpsys stats --metadata [-v] [--proto]
209 * Format for data report: adb shell dumpsys stats [anything other than --metadata] [--proto]
210 * Anything ending in --proto will be in proto format.
211 * Anything without --metadata as the first argument will be report information.
212 * (bugreports call "adb shell dumpsys stats --dump-priority NORMAL -a --proto")
213 * TODO: Come up with a more robust method of enacting <serviceutils/PriorityDumper.h>.
214 */
dump(int fd,const char ** args,uint32_t numArgs)215 status_t StatsService::dump(int fd, const char** args, uint32_t numArgs) {
216 if (!checkPermission(kPermissionDump)) {
217 return PERMISSION_DENIED;
218 }
219
220 int lastArg = numArgs - 1;
221 bool asProto = false;
222 if (lastArg >= 0 && string(args[lastArg]) == "--proto") { // last argument
223 asProto = true;
224 lastArg--;
225 }
226 if (numArgs > 0 && string(args[0]) == "--metadata") { // first argument
227 // Request is to dump statsd stats.
228 bool verbose = false;
229 if (lastArg >= 0 && string(args[lastArg]) == "-v") {
230 verbose = true;
231 lastArg--;
232 }
233 dumpStatsdStats(fd, verbose, asProto);
234 } else {
235 // Request is to dump statsd report data.
236 if (asProto) {
237 dumpIncidentSection(fd);
238 } else {
239 dprintf(fd, "Non-proto format of stats data dump not available; see proto version.\n");
240 }
241 }
242
243 return NO_ERROR;
244 }
245
246 /**
247 * Write debugging data about statsd in text or proto format.
248 */
dumpStatsdStats(int out,bool verbose,bool proto)249 void StatsService::dumpStatsdStats(int out, bool verbose, bool proto) {
250 if (proto) {
251 vector<uint8_t> data;
252 StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats.
253 for (size_t i = 0; i < data.size(); i ++) {
254 dprintf(out, "%c", data[i]);
255 }
256 } else {
257 StatsdStats::getInstance().dumpStats(out);
258 mProcessor->dumpStates(out, verbose);
259 }
260 }
261
262 /**
263 * Write stats report data in StatsDataDumpProto incident section format.
264 */
dumpIncidentSection(int out)265 void StatsService::dumpIncidentSection(int out) {
266 ProtoOutputStream proto;
267 for (const ConfigKey& configKey : mConfigManager->GetAllConfigKeys()) {
268 uint64_t reportsListToken =
269 proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS_LIST);
270 // Don't include the current bucket to avoid skipping buckets.
271 // If we need to include the current bucket later, consider changing to NO_TIME_CONSTRAINTS
272 // or other alternatives to avoid skipping buckets for pulled metrics.
273 mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
274 false /* includeCurrentBucket */, false /* erase_data */,
275 ADB_DUMP,
276 FAST,
277 &proto);
278 proto.end(reportsListToken);
279 proto.flush(out);
280 proto.clear();
281 }
282 }
283
284 /**
285 * Implementation of the adb shell cmd stats command.
286 */
handleShellCommand(int in,int out,int err,const char ** argv,uint32_t argc)287 status_t StatsService::handleShellCommand(int in, int out, int err, const char** argv,
288 uint32_t argc) {
289 uid_t uid = AIBinder_getCallingUid();
290 if (uid != AID_ROOT && uid != AID_SHELL) {
291 return PERMISSION_DENIED;
292 }
293
294 Vector<String8> utf8Args;
295 utf8Args.setCapacity(argc);
296 for (uint32_t i = 0; i < argc; i++) {
297 utf8Args.push(String8(argv[i]));
298 }
299
300 if (argc >= 1) {
301 // adb shell cmd stats config ...
302 if (!utf8Args[0].compare(String8("config"))) {
303 return cmd_config(in, out, err, utf8Args);
304 }
305
306 if (!utf8Args[0].compare(String8("print-uid-map"))) {
307 return cmd_print_uid_map(out, utf8Args);
308 }
309
310 if (!utf8Args[0].compare(String8("dump-report"))) {
311 return cmd_dump_report(out, utf8Args);
312 }
313
314 if (!utf8Args[0].compare(String8("pull-source")) && argc > 1) {
315 return cmd_print_pulled_metrics(out, utf8Args);
316 }
317
318 if (!utf8Args[0].compare(String8("send-broadcast"))) {
319 return cmd_trigger_broadcast(out, utf8Args);
320 }
321
322 if (!utf8Args[0].compare(String8("print-stats"))) {
323 return cmd_print_stats(out, utf8Args);
324 }
325
326 if (!utf8Args[0].compare(String8("meminfo"))) {
327 return cmd_dump_memory_info(out);
328 }
329
330 if (!utf8Args[0].compare(String8("write-to-disk"))) {
331 return cmd_write_data_to_disk(out);
332 }
333
334 if (!utf8Args[0].compare(String8("log-app-breadcrumb"))) {
335 return cmd_log_app_breadcrumb(out, utf8Args);
336 }
337
338 if (!utf8Args[0].compare(String8("log-binary-push"))) {
339 return cmd_log_binary_push(out, utf8Args);
340 }
341
342 if (!utf8Args[0].compare(String8("clear-puller-cache"))) {
343 return cmd_clear_puller_cache(out);
344 }
345
346 if (!utf8Args[0].compare(String8("print-logs"))) {
347 return cmd_print_logs(out, utf8Args);
348 }
349
350 if (!utf8Args[0].compare(String8("send-active-configs"))) {
351 return cmd_trigger_active_config_broadcast(out, utf8Args);
352 }
353
354 if (!utf8Args[0].compare(String8("data-subscribe"))) {
355 {
356 std::lock_guard<std::mutex> lock(mShellSubscriberMutex);
357 if (mShellSubscriber == nullptr) {
358 mShellSubscriber = new ShellSubscriber(mUidMap, mPullerManager);
359 }
360 }
361 int timeoutSec = -1;
362 if (argc >= 2) {
363 timeoutSec = atoi(utf8Args[1].c_str());
364 }
365 mShellSubscriber->startNewSubscription(in, out, timeoutSec);
366 return NO_ERROR;
367 }
368 }
369
370 print_cmd_help(out);
371 return NO_ERROR;
372 }
373
print_cmd_help(int out)374 void StatsService::print_cmd_help(int out) {
375 dprintf(out,
376 "usage: adb shell cmd stats print-stats-log [tag_required] "
377 "[timestamp_nsec_optional]\n");
378 dprintf(out, "\n");
379 dprintf(out, "\n");
380 dprintf(out, "usage: adb shell cmd stats meminfo\n");
381 dprintf(out, "\n");
382 dprintf(out, " Prints the malloc debug information. You need to run the following first: \n");
383 dprintf(out, " # adb shell stop\n");
384 dprintf(out, " # adb shell setprop libc.debug.malloc.program statsd \n");
385 dprintf(out, " # adb shell setprop libc.debug.malloc.options backtrace \n");
386 dprintf(out, " # adb shell start\n");
387 dprintf(out, "\n");
388 dprintf(out, "\n");
389 dprintf(out, "usage: adb shell cmd stats print-uid-map [PKG]\n");
390 dprintf(out, "\n");
391 dprintf(out, " Prints the UID, app name, version mapping.\n");
392 dprintf(out, " PKG Optional package name to print the uids of the package\n");
393 dprintf(out, "\n");
394 dprintf(out, "\n");
395 dprintf(out, "usage: adb shell cmd stats pull-source ATOM_TAG [PACKAGE] \n");
396 dprintf(out, "\n");
397 dprintf(out, " Prints the output of a pulled atom\n");
398 dprintf(out, " UID The atom to pull\n");
399 dprintf(out, " PACKAGE The package to pull from. Default is AID_SYSTEM\n");
400 dprintf(out, "\n");
401 dprintf(out, "\n");
402 dprintf(out, "usage: adb shell cmd stats write-to-disk \n");
403 dprintf(out, "\n");
404 dprintf(out, " Flushes all data on memory to disk.\n");
405 dprintf(out, "\n");
406 dprintf(out, "\n");
407 dprintf(out, "usage: adb shell cmd stats log-app-breadcrumb [UID] LABEL STATE\n");
408 dprintf(out, " Writes an AppBreadcrumbReported event to the statslog buffer.\n");
409 dprintf(out, " UID The uid to use. It is only possible to pass a UID\n");
410 dprintf(out, " parameter on eng builds. If UID is omitted the calling\n");
411 dprintf(out, " uid is used.\n");
412 dprintf(out, " LABEL Integer in [0, 15], as per atoms.proto.\n");
413 dprintf(out, " STATE Integer in [0, 3], as per atoms.proto.\n");
414 dprintf(out, "\n");
415 dprintf(out, "\n");
416 dprintf(out,
417 "usage: adb shell cmd stats log-binary-push NAME VERSION STAGING ROLLBACK_ENABLED "
418 "LOW_LATENCY STATE EXPERIMENT_IDS\n");
419 dprintf(out, " Log a binary push state changed event.\n");
420 dprintf(out, " NAME The train name.\n");
421 dprintf(out, " VERSION The train version code.\n");
422 dprintf(out, " STAGING If this train requires a restart.\n");
423 dprintf(out, " ROLLBACK_ENABLED If rollback should be enabled for this install.\n");
424 dprintf(out, " LOW_LATENCY If the train requires low latency monitoring.\n");
425 dprintf(out, " STATE The status of the train push.\n");
426 dprintf(out, " Integer value of the enum in atoms.proto.\n");
427 dprintf(out, " EXPERIMENT_IDS Comma separated list of experiment ids.\n");
428 dprintf(out, " Leave blank for none.\n");
429 dprintf(out, "\n");
430 dprintf(out, "\n");
431 dprintf(out, "usage: adb shell cmd stats config remove [UID] [NAME]\n");
432 dprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
433 dprintf(out, "\n");
434 dprintf(out, " Adds, updates or removes a configuration. The proto should be in\n");
435 dprintf(out, " wire-encoded protobuf format and passed via stdin. If no UID and name is\n");
436 dprintf(out, " provided, then all configs will be removed from memory and disk.\n");
437 dprintf(out, "\n");
438 dprintf(out, " UID The uid to use. It is only possible to pass the UID\n");
439 dprintf(out, " parameter on eng builds. If UID is omitted the calling\n");
440 dprintf(out, " uid is used.\n");
441 dprintf(out, " NAME The per-uid name to use\n");
442 dprintf(out, "\n");
443 dprintf(out, "\n *Note: If both UID and NAME are omitted then all configs will\n");
444 dprintf(out, "\n be removed from memory and disk!\n");
445 dprintf(out, "\n");
446 dprintf(out,
447 "usage: adb shell cmd stats dump-report [UID] NAME [--keep_data] "
448 "[--include_current_bucket] [--proto]\n");
449 dprintf(out, " Dump all metric data for a configuration.\n");
450 dprintf(out, " UID The uid of the configuration. It is only possible to pass\n");
451 dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n");
452 dprintf(out, " calling uid is used.\n");
453 dprintf(out, " NAME The name of the configuration\n");
454 dprintf(out, " --keep_data Do NOT erase the data upon dumping it.\n");
455 dprintf(out, " --proto Print proto binary.\n");
456 dprintf(out, "\n");
457 dprintf(out, "\n");
458 dprintf(out, "usage: adb shell cmd stats send-broadcast [UID] NAME\n");
459 dprintf(out, " Send a broadcast that triggers the subscriber to fetch metrics.\n");
460 dprintf(out, " UID The uid of the configuration. It is only possible to pass\n");
461 dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n");
462 dprintf(out, " calling uid is used.\n");
463 dprintf(out, " NAME The name of the configuration\n");
464 dprintf(out, "\n");
465 dprintf(out, "\n");
466 dprintf(out,
467 "usage: adb shell cmd stats send-active-configs [--uid=UID] [--configs] "
468 "[NAME1] [NAME2] [NAME3..]\n");
469 dprintf(out, " Send a broadcast that informs the subscriber of the current active configs.\n");
470 dprintf(out, " --uid=UID The uid of the configurations. It is only possible to pass\n");
471 dprintf(out, " the UID parameter on eng builds. If UID is omitted the\n");
472 dprintf(out, " calling uid is used.\n");
473 dprintf(out, " --configs Send the list of configs in the name list instead of\n");
474 dprintf(out, " the currently active configs\n");
475 dprintf(out, " NAME LIST List of configuration names to be included in the broadcast.\n");
476 dprintf(out, "\n");
477 dprintf(out, "\n");
478 dprintf(out, "usage: adb shell cmd stats print-stats\n");
479 dprintf(out, " Prints some basic stats.\n");
480 dprintf(out, " --proto Print proto binary instead of string format.\n");
481 dprintf(out, "\n");
482 dprintf(out, "\n");
483 dprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
484 dprintf(out, " Clear cached puller data.\n");
485 dprintf(out, "\n");
486 dprintf(out, "usage: adb shell cmd stats print-logs\n");
487 dprintf(out, " Only works on eng build\n");
488 }
489
cmd_trigger_broadcast(int out,Vector<String8> & args)490 status_t StatsService::cmd_trigger_broadcast(int out, Vector<String8>& args) {
491 string name;
492 bool good = false;
493 int uid;
494 const int argCount = args.size();
495 if (argCount == 2) {
496 // Automatically pick the UID
497 uid = AIBinder_getCallingUid();
498 name.assign(args[1].c_str(), args[1].size());
499 good = true;
500 } else if (argCount == 3) {
501 good = getUidFromArgs(args, 1, uid);
502 if (!good) {
503 dprintf(out, "Invalid UID. Note that the metrics can only be dumped for "
504 "other UIDs on eng or userdebug builds.\n");
505 }
506 name.assign(args[2].c_str(), args[2].size());
507 }
508 if (!good) {
509 print_cmd_help(out);
510 return UNKNOWN_ERROR;
511 }
512 ConfigKey key(uid, StrToInt64(name));
513 shared_ptr<IPendingIntentRef> receiver = mConfigManager->GetConfigReceiver(key);
514 if (receiver == nullptr) {
515 VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str());
516 return UNKNOWN_ERROR;
517 } else if (receiver->sendDataBroadcast(mProcessor->getLastReportTimeNs(key)).isOk()) {
518 VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(),
519 args[2].c_str());
520 } else {
521 VLOG("StatsService::trigger broadcast failed to %s, %s", args[1].c_str(), args[2].c_str());
522 return UNKNOWN_ERROR;
523 }
524 return NO_ERROR;
525 }
526
cmd_trigger_active_config_broadcast(int out,Vector<String8> & args)527 status_t StatsService::cmd_trigger_active_config_broadcast(int out, Vector<String8>& args) {
528 const int argCount = args.size();
529 int uid;
530 vector<int64_t> configIds;
531 if (argCount == 1) {
532 // Automatically pick the uid and send a broadcast that has no active configs.
533 uid = AIBinder_getCallingUid();
534 mProcessor->GetActiveConfigs(uid, configIds);
535 } else {
536 int curArg = 1;
537 if(args[curArg].find("--uid=") == 0) {
538 string uidArgStr(args[curArg].c_str());
539 string uidStr = uidArgStr.substr(6);
540 if (!getUidFromString(uidStr.c_str(), uid)) {
541 dprintf(out, "Invalid UID. Note that the config can only be set for "
542 "other UIDs on eng or userdebug builds.\n");
543 return UNKNOWN_ERROR;
544 }
545 curArg++;
546 } else {
547 uid = AIBinder_getCallingUid();
548 }
549 if (curArg == argCount || args[curArg] != "--configs") {
550 VLOG("Reached end of args, or specify configs not set. Sending actual active configs,");
551 mProcessor->GetActiveConfigs(uid, configIds);
552 } else {
553 // Flag specified, use the given list of configs.
554 curArg++;
555 for (int i = curArg; i < argCount; i++) {
556 char* endp;
557 int64_t configID = strtoll(args[i].c_str(), &endp, 10);
558 if (endp == args[i].c_str() || *endp != '\0') {
559 dprintf(out, "Error parsing config ID.\n");
560 return UNKNOWN_ERROR;
561 }
562 VLOG("Adding config id %ld", static_cast<long>(configID));
563 configIds.push_back(configID);
564 }
565 }
566 }
567 shared_ptr<IPendingIntentRef> receiver = mConfigManager->GetActiveConfigsChangedReceiver(uid);
568 if (receiver == nullptr) {
569 VLOG("Could not find receiver for uid %d", uid);
570 return UNKNOWN_ERROR;
571 } else if (receiver->sendActiveConfigsChangedBroadcast(configIds).isOk()) {
572 VLOG("StatsService::trigger active configs changed broadcast succeeded for uid %d" , uid);
573 } else {
574 VLOG("StatsService::trigger active configs changed broadcast failed for uid %d", uid);
575 return UNKNOWN_ERROR;
576 }
577 return NO_ERROR;
578 }
579
cmd_config(int in,int out,int err,Vector<String8> & args)580 status_t StatsService::cmd_config(int in, int out, int err, Vector<String8>& args) {
581 const int argCount = args.size();
582 if (argCount >= 2) {
583 if (args[1] == "update" || args[1] == "remove") {
584 bool good = false;
585 int uid = -1;
586 string name;
587
588 if (argCount == 3) {
589 // Automatically pick the UID
590 uid = AIBinder_getCallingUid();
591 name.assign(args[2].c_str(), args[2].size());
592 good = true;
593 } else if (argCount == 4) {
594 good = getUidFromArgs(args, 2, uid);
595 if (!good) {
596 dprintf(err, "Invalid UID. Note that the config can only be set for "
597 "other UIDs on eng or userdebug builds.\n");
598 }
599 name.assign(args[3].c_str(), args[3].size());
600 } else if (argCount == 2 && args[1] == "remove") {
601 good = true;
602 }
603
604 if (!good) {
605 // If arg parsing failed, print the help text and return an error.
606 print_cmd_help(out);
607 return UNKNOWN_ERROR;
608 }
609
610 if (args[1] == "update") {
611 char* endp;
612 int64_t configID = strtoll(name.c_str(), &endp, 10);
613 if (endp == name.c_str() || *endp != '\0') {
614 dprintf(err, "Error parsing config ID.\n");
615 return UNKNOWN_ERROR;
616 }
617
618 // Read stream into buffer.
619 string buffer;
620 if (!android::base::ReadFdToString(in, &buffer)) {
621 dprintf(err, "Error reading stream for StatsConfig.\n");
622 return UNKNOWN_ERROR;
623 }
624
625 // Parse buffer.
626 StatsdConfig config;
627 if (!config.ParseFromString(buffer)) {
628 dprintf(err, "Error parsing proto stream for StatsConfig.\n");
629 return UNKNOWN_ERROR;
630 }
631
632 // Add / update the config.
633 mConfigManager->UpdateConfig(ConfigKey(uid, configID), config);
634 } else {
635 if (argCount == 2) {
636 cmd_remove_all_configs(out);
637 } else {
638 // Remove the config.
639 mConfigManager->RemoveConfig(ConfigKey(uid, StrToInt64(name)));
640 }
641 }
642
643 return NO_ERROR;
644 }
645 }
646 print_cmd_help(out);
647 return UNKNOWN_ERROR;
648 }
649
cmd_dump_report(int out,const Vector<String8> & args)650 status_t StatsService::cmd_dump_report(int out, const Vector<String8>& args) {
651 if (mProcessor != nullptr) {
652 int argCount = args.size();
653 bool good = false;
654 bool proto = false;
655 bool includeCurrentBucket = false;
656 bool eraseData = true;
657 int uid;
658 string name;
659 if (!std::strcmp("--proto", args[argCount-1].c_str())) {
660 proto = true;
661 argCount -= 1;
662 }
663 if (!std::strcmp("--include_current_bucket", args[argCount-1].c_str())) {
664 includeCurrentBucket = true;
665 argCount -= 1;
666 }
667 if (!std::strcmp("--keep_data", args[argCount-1].c_str())) {
668 eraseData = false;
669 argCount -= 1;
670 }
671 if (argCount == 2) {
672 // Automatically pick the UID
673 uid = AIBinder_getCallingUid();
674 name.assign(args[1].c_str(), args[1].size());
675 good = true;
676 } else if (argCount == 3) {
677 good = getUidFromArgs(args, 1, uid);
678 if (!good) {
679 dprintf(out, "Invalid UID. Note that the metrics can only be dumped for "
680 "other UIDs on eng or userdebug builds.\n");
681 }
682 name.assign(args[2].c_str(), args[2].size());
683 }
684 if (good) {
685 vector<uint8_t> data;
686 mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
687 includeCurrentBucket, eraseData, ADB_DUMP,
688 NO_TIME_CONSTRAINTS,
689 &data);
690 if (proto) {
691 for (size_t i = 0; i < data.size(); i ++) {
692 dprintf(out, "%c", data[i]);
693 }
694 } else {
695 dprintf(out, "Non-proto stats data dump not currently supported.\n");
696 }
697 return android::OK;
698 } else {
699 // If arg parsing failed, print the help text and return an error.
700 print_cmd_help(out);
701 return UNKNOWN_ERROR;
702 }
703 } else {
704 dprintf(out, "Log processor does not exist...\n");
705 return UNKNOWN_ERROR;
706 }
707 }
708
cmd_print_stats(int out,const Vector<String8> & args)709 status_t StatsService::cmd_print_stats(int out, const Vector<String8>& args) {
710 int argCount = args.size();
711 bool proto = false;
712 if (!std::strcmp("--proto", args[argCount-1].c_str())) {
713 proto = true;
714 argCount -= 1;
715 }
716 StatsdStats& statsdStats = StatsdStats::getInstance();
717 if (proto) {
718 vector<uint8_t> data;
719 statsdStats.dumpStats(&data, false); // does not reset statsdStats.
720 for (size_t i = 0; i < data.size(); i ++) {
721 dprintf(out, "%c", data[i]);
722 }
723
724 } else {
725 vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
726 for (const ConfigKey& key : configs) {
727 dprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
728 mProcessor->GetMetricsSize(key));
729 }
730 statsdStats.dumpStats(out);
731 }
732 return NO_ERROR;
733 }
734
cmd_print_uid_map(int out,const Vector<String8> & args)735 status_t StatsService::cmd_print_uid_map(int out, const Vector<String8>& args) {
736 if (args.size() > 1) {
737 string pkg;
738 pkg.assign(args[1].c_str(), args[1].size());
739 auto uids = mUidMap->getAppUid(pkg);
740 dprintf(out, "%s -> [ ", pkg.c_str());
741 for (const auto& uid : uids) {
742 dprintf(out, "%d ", uid);
743 }
744 dprintf(out, "]\n");
745 } else {
746 mUidMap->printUidMap(out);
747 }
748 return NO_ERROR;
749 }
750
cmd_write_data_to_disk(int out)751 status_t StatsService::cmd_write_data_to_disk(int out) {
752 dprintf(out, "Writing data to disk\n");
753 mProcessor->WriteDataToDisk(ADB_DUMP, NO_TIME_CONSTRAINTS);
754 return NO_ERROR;
755 }
756
cmd_log_app_breadcrumb(int out,const Vector<String8> & args)757 status_t StatsService::cmd_log_app_breadcrumb(int out, const Vector<String8>& args) {
758 bool good = false;
759 int32_t uid;
760 int32_t label;
761 int32_t state;
762 const int argCount = args.size();
763 if (argCount == 3) {
764 // Automatically pick the UID
765 uid = AIBinder_getCallingUid();
766 label = atoi(args[1].c_str());
767 state = atoi(args[2].c_str());
768 good = true;
769 } else if (argCount == 4) {
770 good = getUidFromArgs(args, 1, uid);
771 if (!good) {
772 dprintf(out,
773 "Invalid UID. Note that selecting a UID for writing AppBreadcrumb can only be "
774 "done for other UIDs on eng or userdebug builds.\n");
775 }
776 label = atoi(args[2].c_str());
777 state = atoi(args[3].c_str());
778 }
779 if (good) {
780 dprintf(out, "Logging AppBreadcrumbReported(%d, %d, %d) to statslog.\n", uid, label, state);
781 android::os::statsd::util::stats_write(
782 android::os::statsd::util::APP_BREADCRUMB_REPORTED, uid, label, state);
783 } else {
784 print_cmd_help(out);
785 return UNKNOWN_ERROR;
786 }
787 return NO_ERROR;
788 }
789
cmd_log_binary_push(int out,const Vector<String8> & args)790 status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args) {
791 // Security checks are done in the sendBinaryPushStateChanged atom.
792 const int argCount = args.size();
793 if (argCount != 7 && argCount != 8) {
794 dprintf(out, "Incorrect number of argument supplied\n");
795 return UNKNOWN_ERROR;
796 }
797 string trainName = string(args[1].c_str());
798 int64_t trainVersion = strtoll(args[2].c_str(), nullptr, 10);
799 int32_t state = atoi(args[6].c_str());
800 vector<int64_t> experimentIds;
801 if (argCount == 8) {
802 vector<string> experimentIdsString = android::base::Split(string(args[7].c_str()), ",");
803 for (string experimentIdString : experimentIdsString) {
804 int64_t experimentId = strtoll(experimentIdString.c_str(), nullptr, 10);
805 experimentIds.push_back(experimentId);
806 }
807 }
808 dprintf(out, "Logging BinaryPushStateChanged\n");
809 vector<uint8_t> experimentIdBytes;
810 writeExperimentIdsToProto(experimentIds, &experimentIdBytes);
811 LogEvent event(trainName, trainVersion, args[3], args[4], args[5], state, experimentIdBytes, 0);
812 mProcessor->OnLogEvent(&event);
813 return NO_ERROR;
814 }
815
cmd_print_pulled_metrics(int out,const Vector<String8> & args)816 status_t StatsService::cmd_print_pulled_metrics(int out, const Vector<String8>& args) {
817 int s = atoi(args[1].c_str());
818 vector<int32_t> uids;
819 if (args.size() > 2) {
820 string package = string(args[2].c_str());
821 auto it = UidMap::sAidToUidMapping.find(package);
822 if (it != UidMap::sAidToUidMapping.end()) {
823 uids.push_back(it->second);
824 } else {
825 set<int32_t> uids_set = mUidMap->getAppUid(package);
826 uids.insert(uids.end(), uids_set.begin(), uids_set.end());
827 }
828 } else {
829 uids.push_back(AID_SYSTEM);
830 }
831 vector<shared_ptr<LogEvent>> stats;
832 if (mPullerManager->Pull(s, uids, getElapsedRealtimeNs(), &stats)) {
833 for (const auto& it : stats) {
834 dprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
835 }
836 dprintf(out, "Pull from %d: Received %zu elements\n", s, stats.size());
837 return NO_ERROR;
838 }
839 return UNKNOWN_ERROR;
840 }
841
cmd_remove_all_configs(int out)842 status_t StatsService::cmd_remove_all_configs(int out) {
843 dprintf(out, "Removing all configs...\n");
844 VLOG("StatsService::cmd_remove_all_configs was called");
845 mConfigManager->RemoveAllConfigs();
846 StorageManager::deleteAllFiles(STATS_SERVICE_DIR);
847 return NO_ERROR;
848 }
849
cmd_dump_memory_info(int out)850 status_t StatsService::cmd_dump_memory_info(int out) {
851 dprintf(out, "meminfo not available.\n");
852 return NO_ERROR;
853 }
854
cmd_clear_puller_cache(int out)855 status_t StatsService::cmd_clear_puller_cache(int out) {
856 VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i",
857 AIBinder_getCallingPid(), AIBinder_getCallingUid());
858 if (checkPermission(kPermissionDump)) {
859 int cleared = mPullerManager->ForceClearPullerCache();
860 dprintf(out, "Puller removed %d cached data!\n", cleared);
861 return NO_ERROR;
862 } else {
863 return PERMISSION_DENIED;
864 }
865 }
866
cmd_print_logs(int out,const Vector<String8> & args)867 status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) {
868 VLOG("StatsService::cmd_print_logs with Pid %i, Uid %i", AIBinder_getCallingPid(),
869 AIBinder_getCallingUid());
870 if (checkPermission(kPermissionDump)) {
871 bool enabled = true;
872 if (args.size() >= 2) {
873 enabled = atoi(args[1].c_str()) != 0;
874 }
875 mProcessor->setPrintLogs(enabled);
876 return NO_ERROR;
877 } else {
878 return PERMISSION_DENIED;
879 }
880 }
881
getUidFromArgs(const Vector<String8> & args,size_t uidArgIndex,int32_t & uid)882 bool StatsService::getUidFromArgs(const Vector<String8>& args, size_t uidArgIndex, int32_t& uid) {
883 return getUidFromString(args[uidArgIndex].c_str(), uid);
884 }
885
getUidFromString(const char * s,int32_t & uid)886 bool StatsService::getUidFromString(const char* s, int32_t& uid) {
887 if (*s == '\0') {
888 return false;
889 }
890 char* endc = NULL;
891 int64_t longUid = strtol(s, &endc, 0);
892 if (*endc != '\0') {
893 return false;
894 }
895 int32_t goodUid = static_cast<int32_t>(longUid);
896 if (longUid < 0 || static_cast<uint64_t>(longUid) != static_cast<uid_t>(goodUid)) {
897 return false; // It was not of uid_t type.
898 }
899 uid = goodUid;
900
901 int32_t callingUid = AIBinder_getCallingUid();
902 return mEngBuild // UserDebug/EngBuild are allowed to impersonate uids.
903 || (callingUid == goodUid) // Anyone can 'impersonate' themselves.
904 || (callingUid == AID_ROOT && goodUid == AID_SHELL); // ROOT can impersonate SHELL.
905 }
906
informAllUidData(const ScopedFileDescriptor & fd)907 Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
908 ENFORCE_UID(AID_SYSTEM);
909 // Read stream into buffer.
910 string buffer;
911 if (!android::base::ReadFdToString(fd.get(), &buffer)) {
912 return exception(EX_ILLEGAL_ARGUMENT, "Failed to read all data from the pipe.");
913 }
914
915 // Parse buffer.
916 UidData uidData;
917 if (!uidData.ParseFromString(buffer)) {
918 return exception(EX_ILLEGAL_ARGUMENT, "Error parsing proto stream for UidData.");
919 }
920
921 vector<String16> versionStrings;
922 vector<String16> installers;
923 vector<String16> packageNames;
924 vector<int32_t> uids;
925 vector<int64_t> versions;
926
927 const auto numEntries = uidData.app_info_size();
928 versionStrings.reserve(numEntries);
929 installers.reserve(numEntries);
930 packageNames.reserve(numEntries);
931 uids.reserve(numEntries);
932 versions.reserve(numEntries);
933
934 for (const auto& appInfo: uidData.app_info()) {
935 packageNames.emplace_back(String16(appInfo.package_name().c_str()));
936 uids.push_back(appInfo.uid());
937 versions.push_back(appInfo.version());
938 versionStrings.emplace_back(String16(appInfo.version_string().c_str()));
939 installers.emplace_back(String16(appInfo.installer().c_str()));
940 }
941
942 mUidMap->updateMap(getElapsedRealtimeNs(),
943 uids,
944 versions,
945 versionStrings,
946 packageNames,
947 installers);
948
949 mBootCompleteTrigger.markComplete(kUidMapReceivedTag);
950 VLOG("StatsService::informAllUidData UidData proto parsed successfully.");
951 return Status::ok();
952 }
953
informOnePackage(const string & app,int32_t uid,int64_t version,const string & versionString,const string & installer)954 Status StatsService::informOnePackage(const string& app, int32_t uid, int64_t version,
955 const string& versionString, const string& installer) {
956 ENFORCE_UID(AID_SYSTEM);
957
958 VLOG("StatsService::informOnePackage was called");
959 String16 utf16App = String16(app.c_str());
960 String16 utf16VersionString = String16(versionString.c_str());
961 String16 utf16Installer = String16(installer.c_str());
962
963 mUidMap->updateApp(getElapsedRealtimeNs(), utf16App, uid, version, utf16VersionString,
964 utf16Installer);
965 return Status::ok();
966 }
967
informOnePackageRemoved(const string & app,int32_t uid)968 Status StatsService::informOnePackageRemoved(const string& app, int32_t uid) {
969 ENFORCE_UID(AID_SYSTEM);
970
971 VLOG("StatsService::informOnePackageRemoved was called");
972 String16 utf16App = String16(app.c_str());
973 mUidMap->removeApp(getElapsedRealtimeNs(), utf16App, uid);
974 mConfigManager->RemoveConfigs(uid);
975 return Status::ok();
976 }
977
informAnomalyAlarmFired()978 Status StatsService::informAnomalyAlarmFired() {
979 ENFORCE_UID(AID_SYSTEM);
980
981 VLOG("StatsService::informAnomalyAlarmFired was called");
982 int64_t currentTimeSec = getElapsedRealtimeSec();
983 std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
984 mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
985 if (alarmSet.size() > 0) {
986 VLOG("Found an anomaly alarm that fired.");
987 mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
988 } else {
989 VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
990 }
991 return Status::ok();
992 }
993
informAlarmForSubscriberTriggeringFired()994 Status StatsService::informAlarmForSubscriberTriggeringFired() {
995 ENFORCE_UID(AID_SYSTEM);
996
997 VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
998 int64_t currentTimeSec = getElapsedRealtimeSec();
999 std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
1000 mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
1001 if (alarmSet.size() > 0) {
1002 VLOG("Found periodic alarm fired.");
1003 mProcessor->onPeriodicAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
1004 } else {
1005 ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
1006 }
1007 return Status::ok();
1008 }
1009
informPollAlarmFired()1010 Status StatsService::informPollAlarmFired() {
1011 ENFORCE_UID(AID_SYSTEM);
1012
1013 VLOG("StatsService::informPollAlarmFired was called");
1014 mProcessor->informPullAlarmFired(getElapsedRealtimeNs());
1015 VLOG("StatsService::informPollAlarmFired succeeded");
1016 return Status::ok();
1017 }
1018
systemRunning()1019 Status StatsService::systemRunning() {
1020 ENFORCE_UID(AID_SYSTEM);
1021
1022 // When system_server is up and running, schedule the dropbox task to run.
1023 VLOG("StatsService::systemRunning");
1024 sayHiToStatsCompanion();
1025 return Status::ok();
1026 }
1027
informDeviceShutdown()1028 Status StatsService::informDeviceShutdown() {
1029 ENFORCE_UID(AID_SYSTEM);
1030 VLOG("StatsService::informDeviceShutdown");
1031 mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST);
1032 mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs());
1033 mProcessor->SaveMetadataToDisk(getWallClockNs(), getElapsedRealtimeNs());
1034 return Status::ok();
1035 }
1036
sayHiToStatsCompanion()1037 void StatsService::sayHiToStatsCompanion() {
1038 shared_ptr<IStatsCompanionService> statsCompanion = getStatsCompanionService();
1039 if (statsCompanion != nullptr) {
1040 VLOG("Telling statsCompanion that statsd is ready");
1041 statsCompanion->statsdReady();
1042 } else {
1043 VLOG("Could not access statsCompanion");
1044 }
1045 }
1046
statsCompanionReady()1047 Status StatsService::statsCompanionReady() {
1048 ENFORCE_UID(AID_SYSTEM);
1049
1050 VLOG("StatsService::statsCompanionReady was called");
1051 shared_ptr<IStatsCompanionService> statsCompanion = getStatsCompanionService();
1052 if (statsCompanion == nullptr) {
1053 return exception(EX_NULL_POINTER,
1054 "StatsCompanion unavailable despite it contacting statsd.");
1055 }
1056 VLOG("StatsService::statsCompanionReady linking to statsCompanion.");
1057 AIBinder_linkToDeath(statsCompanion->asBinder().get(),
1058 mStatsCompanionServiceDeathRecipient.get(), this);
1059 mPullerManager->SetStatsCompanionService(statsCompanion);
1060 mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion);
1061 mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion);
1062 return Status::ok();
1063 }
1064
bootCompleted()1065 Status StatsService::bootCompleted() {
1066 ENFORCE_UID(AID_SYSTEM);
1067
1068 VLOG("StatsService::bootCompleted was called");
1069 mBootCompleteTrigger.markComplete(kBootCompleteTag);
1070 return Status::ok();
1071 }
1072
Startup()1073 void StatsService::Startup() {
1074 mConfigManager->Startup();
1075 mProcessor->LoadActiveConfigsFromDisk();
1076 mProcessor->LoadMetadataFromDisk(getWallClockNs(), getElapsedRealtimeNs());
1077 }
1078
Terminate()1079 void StatsService::Terminate() {
1080 ALOGI("StatsService::Terminating");
1081 if (mProcessor != nullptr) {
1082 mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST);
1083 mProcessor->SaveActiveConfigsToDisk(getElapsedRealtimeNs());
1084 mProcessor->SaveMetadataToDisk(getWallClockNs(), getElapsedRealtimeNs());
1085 }
1086 }
1087
1088 // Test only interface!!!
OnLogEvent(LogEvent * event)1089 void StatsService::OnLogEvent(LogEvent* event) {
1090 mProcessor->OnLogEvent(event);
1091 if (mShellSubscriber != nullptr) {
1092 mShellSubscriber->onLogEvent(*event);
1093 }
1094 }
1095
getData(int64_t key,const int32_t callingUid,vector<int8_t> * output)1096 Status StatsService::getData(int64_t key, const int32_t callingUid, vector<int8_t>* output) {
1097 ENFORCE_UID(AID_SYSTEM);
1098
1099 VLOG("StatsService::getData with Uid %i", callingUid);
1100 ConfigKey configKey(callingUid, key);
1101 // TODO(b/149254662): Since libbinder_ndk uses int8_t instead of uint8_t,
1102 // there are inconsistencies with internal statsd logic. Instead of
1103 // modifying lots of files, we create a temporary output array of int8_t and
1104 // copy its data into output. This is a bad hack, but hopefully
1105 // libbinder_ndk will transition to using uint8_t soon: progress is tracked
1106 // in b/144957764. Same applies to StatsService::getMetadata.
1107 vector<uint8_t> unsignedOutput;
1108 // The dump latency does not matter here since we do not include the current bucket, we do not
1109 // need to pull any new data anyhow.
1110 mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/,
1111 true /* erase_data */, GET_DATA_CALLED, FAST, &unsignedOutput);
1112 *output = vector<int8_t>(unsignedOutput.begin(), unsignedOutput.end());
1113 return Status::ok();
1114 }
1115
getMetadata(vector<int8_t> * output)1116 Status StatsService::getMetadata(vector<int8_t>* output) {
1117 ENFORCE_UID(AID_SYSTEM);
1118
1119 vector<uint8_t> unsignedOutput;
1120 StatsdStats::getInstance().dumpStats(&unsignedOutput, false); // Don't reset the counters.
1121 *output = vector<int8_t>(unsignedOutput.begin(), unsignedOutput.end());
1122 return Status::ok();
1123 }
1124
addConfiguration(int64_t key,const vector<int8_t> & config,const int32_t callingUid)1125 Status StatsService::addConfiguration(int64_t key, const vector <int8_t>& config,
1126 const int32_t callingUid) {
1127 ENFORCE_UID(AID_SYSTEM);
1128
1129 if (addConfigurationChecked(callingUid, key, config)) {
1130 return Status::ok();
1131 } else {
1132 return exception(EX_ILLEGAL_ARGUMENT, "Could not parse malformatted StatsdConfig.");
1133 }
1134 }
1135
addConfigurationChecked(int uid,int64_t key,const vector<int8_t> & config)1136 bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<int8_t>& config) {
1137 ConfigKey configKey(uid, key);
1138 StatsdConfig cfg;
1139 if (config.size() > 0) { // If the config is empty, skip parsing.
1140 if (!cfg.ParseFromArray(&config[0], config.size())) {
1141 return false;
1142 }
1143 }
1144 mConfigManager->UpdateConfig(configKey, cfg);
1145 return true;
1146 }
1147
removeDataFetchOperation(int64_t key,const int32_t callingUid)1148 Status StatsService::removeDataFetchOperation(int64_t key,
1149 const int32_t callingUid) {
1150 ENFORCE_UID(AID_SYSTEM);
1151 ConfigKey configKey(callingUid, key);
1152 mConfigManager->RemoveConfigReceiver(configKey);
1153 return Status::ok();
1154 }
1155
setDataFetchOperation(int64_t key,const shared_ptr<IPendingIntentRef> & pir,const int32_t callingUid)1156 Status StatsService::setDataFetchOperation(int64_t key,
1157 const shared_ptr<IPendingIntentRef>& pir,
1158 const int32_t callingUid) {
1159 ENFORCE_UID(AID_SYSTEM);
1160
1161 ConfigKey configKey(callingUid, key);
1162 mConfigManager->SetConfigReceiver(configKey, pir);
1163 if (StorageManager::hasConfigMetricsReport(configKey)) {
1164 VLOG("StatsService::setDataFetchOperation marking configKey %s to dump reports on disk",
1165 configKey.ToString().c_str());
1166 mProcessor->noteOnDiskData(configKey);
1167 }
1168 return Status::ok();
1169 }
1170
setActiveConfigsChangedOperation(const shared_ptr<IPendingIntentRef> & pir,const int32_t callingUid,vector<int64_t> * output)1171 Status StatsService::setActiveConfigsChangedOperation(const shared_ptr<IPendingIntentRef>& pir,
1172 const int32_t callingUid,
1173 vector<int64_t>* output) {
1174 ENFORCE_UID(AID_SYSTEM);
1175
1176 mConfigManager->SetActiveConfigsChangedReceiver(callingUid, pir);
1177 if (output != nullptr) {
1178 mProcessor->GetActiveConfigs(callingUid, *output);
1179 } else {
1180 ALOGW("StatsService::setActiveConfigsChanged output was nullptr");
1181 }
1182 return Status::ok();
1183 }
1184
removeActiveConfigsChangedOperation(const int32_t callingUid)1185 Status StatsService::removeActiveConfigsChangedOperation(const int32_t callingUid) {
1186 ENFORCE_UID(AID_SYSTEM);
1187
1188 mConfigManager->RemoveActiveConfigsChangedReceiver(callingUid);
1189 return Status::ok();
1190 }
1191
removeConfiguration(int64_t key,const int32_t callingUid)1192 Status StatsService::removeConfiguration(int64_t key, const int32_t callingUid) {
1193 ENFORCE_UID(AID_SYSTEM);
1194
1195 ConfigKey configKey(callingUid, key);
1196 mConfigManager->RemoveConfig(configKey);
1197 return Status::ok();
1198 }
1199
setBroadcastSubscriber(int64_t configId,int64_t subscriberId,const shared_ptr<IPendingIntentRef> & pir,const int32_t callingUid)1200 Status StatsService::setBroadcastSubscriber(int64_t configId,
1201 int64_t subscriberId,
1202 const shared_ptr<IPendingIntentRef>& pir,
1203 const int32_t callingUid) {
1204 ENFORCE_UID(AID_SYSTEM);
1205
1206 VLOG("StatsService::setBroadcastSubscriber called.");
1207 ConfigKey configKey(callingUid, configId);
1208 SubscriberReporter::getInstance()
1209 .setBroadcastSubscriber(configKey, subscriberId, pir);
1210 return Status::ok();
1211 }
1212
unsetBroadcastSubscriber(int64_t configId,int64_t subscriberId,const int32_t callingUid)1213 Status StatsService::unsetBroadcastSubscriber(int64_t configId,
1214 int64_t subscriberId,
1215 const int32_t callingUid) {
1216 ENFORCE_UID(AID_SYSTEM);
1217
1218 VLOG("StatsService::unsetBroadcastSubscriber called.");
1219 ConfigKey configKey(callingUid, configId);
1220 SubscriberReporter::getInstance()
1221 .unsetBroadcastSubscriber(configKey, subscriberId);
1222 return Status::ok();
1223 }
1224
allPullersFromBootRegistered()1225 Status StatsService::allPullersFromBootRegistered() {
1226 ENFORCE_UID(AID_SYSTEM);
1227
1228 VLOG("StatsService::allPullersFromBootRegistered was called");
1229 mBootCompleteTrigger.markComplete(kAllPullersRegisteredTag);
1230 return Status::ok();
1231 }
1232
registerPullAtomCallback(int32_t uid,int32_t atomTag,int64_t coolDownMillis,int64_t timeoutMillis,const std::vector<int32_t> & additiveFields,const shared_ptr<IPullAtomCallback> & pullerCallback)1233 Status StatsService::registerPullAtomCallback(int32_t uid, int32_t atomTag, int64_t coolDownMillis,
1234 int64_t timeoutMillis,
1235 const std::vector<int32_t>& additiveFields,
1236 const shared_ptr<IPullAtomCallback>& pullerCallback) {
1237 ENFORCE_UID(AID_SYSTEM);
1238 VLOG("StatsService::registerPullAtomCallback called.");
1239 mPullerManager->RegisterPullAtomCallback(uid, atomTag, MillisToNano(coolDownMillis),
1240 MillisToNano(timeoutMillis), additiveFields,
1241 pullerCallback);
1242 return Status::ok();
1243 }
1244
registerNativePullAtomCallback(int32_t atomTag,int64_t coolDownMillis,int64_t timeoutMillis,const std::vector<int32_t> & additiveFields,const shared_ptr<IPullAtomCallback> & pullerCallback)1245 Status StatsService::registerNativePullAtomCallback(
1246 int32_t atomTag, int64_t coolDownMillis, int64_t timeoutMillis,
1247 const std::vector<int32_t>& additiveFields,
1248 const shared_ptr<IPullAtomCallback>& pullerCallback) {
1249 if (!checkPermission(kPermissionRegisterPullAtom)) {
1250 return exception(
1251 EX_SECURITY,
1252 StringPrintf("Uid %d does not have the %s permission when registering atom %d",
1253 AIBinder_getCallingUid(), kPermissionRegisterPullAtom, atomTag));
1254 }
1255 VLOG("StatsService::registerNativePullAtomCallback called.");
1256 int32_t uid = AIBinder_getCallingUid();
1257 mPullerManager->RegisterPullAtomCallback(uid, atomTag, MillisToNano(coolDownMillis),
1258 MillisToNano(timeoutMillis), additiveFields,
1259 pullerCallback);
1260 return Status::ok();
1261 }
1262
unregisterPullAtomCallback(int32_t uid,int32_t atomTag)1263 Status StatsService::unregisterPullAtomCallback(int32_t uid, int32_t atomTag) {
1264 ENFORCE_UID(AID_SYSTEM);
1265 VLOG("StatsService::unregisterPullAtomCallback called.");
1266 mPullerManager->UnregisterPullAtomCallback(uid, atomTag);
1267 return Status::ok();
1268 }
1269
unregisterNativePullAtomCallback(int32_t atomTag)1270 Status StatsService::unregisterNativePullAtomCallback(int32_t atomTag) {
1271 if (!checkPermission(kPermissionRegisterPullAtom)) {
1272 return exception(
1273 EX_SECURITY,
1274 StringPrintf("Uid %d does not have the %s permission when unregistering atom %d",
1275 AIBinder_getCallingUid(), kPermissionRegisterPullAtom, atomTag));
1276 }
1277 VLOG("StatsService::unregisterNativePullAtomCallback called.");
1278 int32_t uid = AIBinder_getCallingUid();
1279 mPullerManager->UnregisterPullAtomCallback(uid, atomTag);
1280 return Status::ok();
1281 }
1282
getRegisteredExperimentIds(std::vector<int64_t> * experimentIdsOut)1283 Status StatsService::getRegisteredExperimentIds(std::vector<int64_t>* experimentIdsOut) {
1284 ENFORCE_UID(AID_SYSTEM);
1285 // TODO: add verifier permission
1286
1287 experimentIdsOut->clear();
1288 // Read the latest train info
1289 vector<InstallTrainInfo> trainInfoList = StorageManager::readAllTrainInfo();
1290 if (trainInfoList.empty()) {
1291 // No train info means no experiment IDs, return an empty list
1292 return Status::ok();
1293 }
1294
1295 // Copy the experiment IDs to the out vector
1296 for (InstallTrainInfo& trainInfo : trainInfoList) {
1297 experimentIdsOut->insert(experimentIdsOut->end(),
1298 trainInfo.experimentIds.begin(),
1299 trainInfo.experimentIds.end());
1300 }
1301 return Status::ok();
1302 }
1303
statsCompanionServiceDied(void * cookie)1304 void StatsService::statsCompanionServiceDied(void* cookie) {
1305 auto thiz = static_cast<StatsService*>(cookie);
1306 thiz->statsCompanionServiceDiedImpl();
1307 }
1308
statsCompanionServiceDiedImpl()1309 void StatsService::statsCompanionServiceDiedImpl() {
1310 ALOGW("statscompanion service died");
1311 StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
1312 if (mProcessor != nullptr) {
1313 ALOGW("Reset statsd upon system server restarts.");
1314 int64_t systemServerRestartNs = getElapsedRealtimeNs();
1315 ProtoOutputStream activeConfigsProto;
1316 mProcessor->WriteActiveConfigsToProtoOutputStream(systemServerRestartNs,
1317 STATSCOMPANION_DIED, &activeConfigsProto);
1318 metadata::StatsMetadataList metadataList;
1319 mProcessor->WriteMetadataToProto(getWallClockNs(),
1320 systemServerRestartNs, &metadataList);
1321 mProcessor->WriteDataToDisk(STATSCOMPANION_DIED, FAST);
1322 mProcessor->resetConfigs();
1323
1324 std::string serializedActiveConfigs;
1325 if (activeConfigsProto.serializeToString(&serializedActiveConfigs)) {
1326 ActiveConfigList activeConfigs;
1327 if (activeConfigs.ParseFromString(serializedActiveConfigs)) {
1328 mProcessor->SetConfigsActiveState(activeConfigs, systemServerRestartNs);
1329 }
1330 }
1331 mProcessor->SetMetadataState(metadataList, getWallClockNs(), systemServerRestartNs);
1332 }
1333 mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
1334 mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
1335 mPullerManager->SetStatsCompanionService(nullptr);
1336 }
1337
1338 } // namespace statsd
1339 } // namespace os
1340 } // namespace android
1341