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