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