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