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