OSDN Git Service

Merge "Add stats logging to ServiceManager and NPMS" into pi-dev
[android-x86/frameworks-base.git] / cmds / statsd / src / StatsService.cpp
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 <binder/IPCThreadState.h>
31 #include <binder/IServiceManager.h>
32 #include <dirent.h>
33 #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
34 #include <private/android_filesystem_config.h>
35 #include <utils/Looper.h>
36 #include <utils/String16.h>
37 #include <statslog.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <sys/system_properties.h>
41 #include <unistd.h>
42
43 using namespace android;
44
45 namespace android {
46 namespace os {
47 namespace statsd {
48
49 constexpr const char* kPermissionDump = "android.permission.DUMP";
50 #define STATS_SERVICE_DIR "/data/misc/stats-service"
51
52 StatsService::StatsService(const sp<Looper>& handlerLooper)
53     : mAnomalyAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
54        [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) {
55            if (sc != nullptr) {
56                sc->setAnomalyAlarm(timeMillis);
57                StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
58            }
59        },
60        [](const sp<IStatsCompanionService>& sc) {
61            if (sc != nullptr) {
62                sc->cancelAnomalyAlarm();
63                StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
64            }
65        })),
66    mPeriodicAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
67       [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) {
68            if (sc != nullptr) {
69                sc->setAlarmForSubscriberTriggering(timeMillis);
70                StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged();
71            }
72       },
73       [](const sp<IStatsCompanionService>& sc) {
74            if (sc != nullptr) {
75                sc->cancelAlarmForSubscriberTriggering();
76                StatsdStats::getInstance().noteRegisteredPeriodicAlarmChanged();
77            }
78
79       }))  {
80     mUidMap = new UidMap();
81     StatsPuller::SetUidMap(mUidMap);
82     mConfigManager = new ConfigManager();
83     mProcessor = new StatsLogProcessor(mUidMap, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
84                                        getElapsedRealtimeNs(), [this](const ConfigKey& key) {
85         sp<IStatsCompanionService> sc = getStatsCompanionService();
86         auto receiver = mConfigManager->GetConfigReceiver(key);
87         if (sc == nullptr) {
88             VLOG("Could not find StatsCompanionService");
89         } else if (receiver == nullptr) {
90             VLOG("Statscompanion could not find a broadcast receiver for %s",
91                  key.ToString().c_str());
92         } else {
93             sc->sendDataBroadcast(receiver);
94         }
95     }
96     );
97
98     mConfigManager->AddListener(mProcessor);
99
100     init_system_properties();
101 }
102
103 StatsService::~StatsService() {
104 }
105
106 void StatsService::init_system_properties() {
107     mEngBuild = false;
108     const prop_info* buildType = __system_property_find("ro.build.type");
109     if (buildType != NULL) {
110         __system_property_read_callback(buildType, init_build_type_callback, this);
111     }
112 }
113
114 void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
115                                             uint32_t serial) {
116     if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) {
117         reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
118     }
119 }
120
121 /**
122  * Implement our own because the default binder implementation isn't
123  * properly handling SHELL_COMMAND_TRANSACTION.
124  */
125 status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
126                                   uint32_t flags) {
127     switch (code) {
128         case SHELL_COMMAND_TRANSACTION: {
129             int in = data.readFileDescriptor();
130             int out = data.readFileDescriptor();
131             int err = data.readFileDescriptor();
132             int argc = data.readInt32();
133             Vector<String8> args;
134             for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
135                 args.add(String8(data.readString16()));
136             }
137             sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
138             sp<IResultReceiver> resultReceiver =
139                     IResultReceiver::asInterface(data.readStrongBinder());
140
141             FILE* fin = fdopen(in, "r");
142             FILE* fout = fdopen(out, "w");
143             FILE* ferr = fdopen(err, "w");
144
145             if (fin == NULL || fout == NULL || ferr == NULL) {
146                 resultReceiver->send(NO_MEMORY);
147             } else {
148                 err = command(fin, fout, ferr, args);
149                 resultReceiver->send(err);
150             }
151
152             if (fin != NULL) {
153                 fflush(fin);
154                 fclose(fin);
155             }
156             if (fout != NULL) {
157                 fflush(fout);
158                 fclose(fout);
159             }
160             if (fout != NULL) {
161                 fflush(ferr);
162                 fclose(ferr);
163             }
164
165             return NO_ERROR;
166         }
167         default: { return BnStatsManager::onTransact(code, data, reply, flags); }
168     }
169 }
170
171 /**
172  * Write debugging data about statsd.
173  */
174 status_t StatsService::dump(int fd, const Vector<String16>& args) {
175     FILE* out = fdopen(fd, "w");
176     if (out == NULL) {
177         return NO_MEMORY;  // the fd is already open
178     }
179
180     bool verbose = false;
181     bool proto = false;
182     if (args.size() > 0 && !args[0].compare(String16("-v"))) {
183         verbose = true;
184     }
185     if (args.size() > 0 && !args[args.size()-1].compare(String16("--proto"))) {
186         proto = true;
187     }
188
189     dump_impl(out, verbose, proto);
190
191     fclose(out);
192     return NO_ERROR;
193 }
194
195 /**
196  * Write debugging data about statsd in text or proto format.
197  */
198 void StatsService::dump_impl(FILE* out, bool verbose, bool proto) {
199     if (proto) {
200         vector<uint8_t> data;
201         StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats.
202         for (size_t i = 0; i < data.size(); i ++) {
203             fprintf(out, "%c", data[i]);
204         }
205     } else {
206         StatsdStats::getInstance().dumpStats(out);
207         mProcessor->dumpStates(out, verbose);
208     }
209 }
210
211 /**
212  * Implementation of the adb shell cmd stats command.
213  */
214 status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
215     // TODO: Permission check
216
217     const int argCount = args.size();
218     if (argCount >= 1) {
219         // adb shell cmd stats config ...
220         if (!args[0].compare(String8("config"))) {
221             return cmd_config(in, out, err, args);
222         }
223
224         if (!args[0].compare(String8("print-uid-map"))) {
225             return cmd_print_uid_map(out, args);
226         }
227
228         if (!args[0].compare(String8("dump-report"))) {
229             return cmd_dump_report(out, err, args);
230         }
231
232         if (!args[0].compare(String8("pull-source")) && args.size() > 1) {
233             return cmd_print_pulled_metrics(out, args);
234         }
235
236         if (!args[0].compare(String8("send-broadcast"))) {
237             return cmd_trigger_broadcast(out, args);
238         }
239
240         if (!args[0].compare(String8("print-stats"))) {
241             return cmd_print_stats(out, args);
242         }
243
244         if (!args[0].compare(String8("meminfo"))) {
245             return cmd_dump_memory_info(out);
246         }
247
248         if (!args[0].compare(String8("write-to-disk"))) {
249             return cmd_write_data_to_disk(out);
250         }
251
252         if (!args[0].compare(String8("log-app-breadcrumb"))) {
253             return cmd_log_app_breadcrumb(out, args);
254         }
255
256         if (!args[0].compare(String8("clear-puller-cache"))) {
257             return cmd_clear_puller_cache(out);
258         }
259     }
260
261     print_cmd_help(out);
262     return NO_ERROR;
263 }
264
265 void StatsService::print_cmd_help(FILE* out) {
266     fprintf(out,
267             "usage: adb shell cmd stats print-stats-log [tag_required] "
268             "[timestamp_nsec_optional]\n");
269     fprintf(out, "\n");
270     fprintf(out, "\n");
271     fprintf(out, "usage: adb shell cmd stats meminfo\n");
272     fprintf(out, "\n");
273     fprintf(out, "  Prints the malloc debug information. You need to run the following first: \n");
274     fprintf(out, "   # adb shell stop\n");
275     fprintf(out, "   # adb shell setprop libc.debug.malloc.program statsd \n");
276     fprintf(out, "   # adb shell setprop libc.debug.malloc.options backtrace \n");
277     fprintf(out, "   # adb shell start\n");
278     fprintf(out, "\n");
279     fprintf(out, "\n");
280     fprintf(out, "usage: adb shell cmd stats print-uid-map [PKG]\n");
281     fprintf(out, "\n");
282     fprintf(out, "  Prints the UID, app name, version mapping.\n");
283     fprintf(out, "  PKG           Optional package name to print the uids of the package\n");
284     fprintf(out, "\n");
285     fprintf(out, "\n");
286     fprintf(out, "usage: adb shell cmd stats pull-source [int] \n");
287     fprintf(out, "\n");
288     fprintf(out, "  Prints the output of a pulled metrics source (int indicates source)\n");
289     fprintf(out, "\n");
290     fprintf(out, "\n");
291     fprintf(out, "usage: adb shell cmd stats write-to-disk \n");
292     fprintf(out, "\n");
293     fprintf(out, "  Flushes all data on memory to disk.\n");
294     fprintf(out, "\n");
295     fprintf(out, "\n");
296     fprintf(out, "usage: adb shell cmd stats log-app-breadcrumb [UID] LABEL STATE\n");
297     fprintf(out, "  Writes an AppBreadcrumbReported event to the statslog buffer.\n");
298     fprintf(out, "  UID           The uid to use. It is only possible to pass a UID\n");
299     fprintf(out, "                parameter on eng builds. If UID is omitted the calling\n");
300     fprintf(out, "                uid is used.\n");
301     fprintf(out, "  LABEL         Integer in [0, 15], as per atoms.proto.\n");
302     fprintf(out, "  STATE         Integer in [0, 3], as per atoms.proto.\n");
303     fprintf(out, "\n");
304     fprintf(out, "\n");
305     fprintf(out, "usage: adb shell cmd stats config remove [UID] [NAME]\n");
306     fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
307     fprintf(out, "\n");
308     fprintf(out, "  Adds, updates or removes a configuration. The proto should be in\n");
309     fprintf(out, "  wire-encoded protobuf format and passed via stdin. If no UID and name is\n");
310     fprintf(out, "  provided, then all configs will be removed from memory and disk.\n");
311     fprintf(out, "\n");
312     fprintf(out, "  UID           The uid to use. It is only possible to pass the UID\n");
313     fprintf(out, "                parameter on eng builds. If UID is omitted the calling\n");
314     fprintf(out, "                uid is used.\n");
315     fprintf(out, "  NAME          The per-uid name to use\n");
316     fprintf(out, "\n");
317     fprintf(out, "\n              *Note: If both UID and NAME are omitted then all configs will\n");
318     fprintf(out, "\n                     be removed from memory and disk!\n");
319     fprintf(out, "\n");
320     fprintf(out, "usage: adb shell cmd stats dump-report [UID] NAME [--proto]\n");
321     fprintf(out, "  Dump all metric data for a configuration.\n");
322     fprintf(out, "  UID           The uid of the configuration. It is only possible to pass\n");
323     fprintf(out, "                the UID parameter on eng builds. If UID is omitted the\n");
324     fprintf(out, "                calling uid is used.\n");
325     fprintf(out, "  NAME          The name of the configuration\n");
326     fprintf(out, "  --proto       Print proto binary.\n");
327     fprintf(out, "\n");
328     fprintf(out, "\n");
329     fprintf(out, "usage: adb shell cmd stats send-broadcast [UID] NAME\n");
330     fprintf(out, "  Send a broadcast that triggers the subscriber to fetch metrics.\n");
331     fprintf(out, "  UID           The uid of the configuration. It is only possible to pass\n");
332     fprintf(out, "                the UID parameter on eng builds. If UID is omitted the\n");
333     fprintf(out, "                calling uid is used.\n");
334     fprintf(out, "  NAME          The name of the configuration\n");
335     fprintf(out, "\n");
336     fprintf(out, "\n");
337     fprintf(out, "usage: adb shell cmd stats print-stats\n");
338     fprintf(out, "  Prints some basic stats.\n");
339     fprintf(out, "  --proto       Print proto binary instead of string format.\n");
340     fprintf(out, "\n");
341     fprintf(out, "\n");
342     fprintf(out, "usage: adb shell cmd stats clear-puller-cache\n");
343     fprintf(out, "  Clear cached puller data.\n");
344 }
345
346 status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
347     string name;
348     bool good = false;
349     int uid;
350     const int argCount = args.size();
351     if (argCount == 2) {
352         // Automatically pick the UID
353         uid = IPCThreadState::self()->getCallingUid();
354         // TODO: What if this isn't a binder call? Should we fail?
355         name.assign(args[1].c_str(), args[1].size());
356         good = true;
357     } else if (argCount == 3) {
358         // If it's a userdebug or eng build, then the shell user can
359         // impersonate other uids.
360         if (mEngBuild) {
361             const char* s = args[1].c_str();
362             if (*s != '\0') {
363                 char* end = NULL;
364                 uid = strtol(s, &end, 0);
365                 if (*end == '\0') {
366                     name.assign(args[2].c_str(), args[2].size());
367                     good = true;
368                 }
369             }
370         } else {
371             fprintf(out,
372                     "The metrics can only be dumped for other UIDs on eng or userdebug "
373                             "builds.\n");
374         }
375     }
376     if (!good) {
377         print_cmd_help(out);
378         return UNKNOWN_ERROR;
379     }
380     auto receiver = mConfigManager->GetConfigReceiver(ConfigKey(uid, StrToInt64(name)));
381     sp<IStatsCompanionService> sc = getStatsCompanionService();
382     if (sc == nullptr) {
383         VLOG("Could not access statsCompanion");
384     } else if (receiver == nullptr) {
385         VLOG("Could not find receiver for %s, %s", args[1].c_str(), args[2].c_str())
386     } else {
387         sc->sendDataBroadcast(receiver);
388         VLOG("StatsService::trigger broadcast succeeded to %s, %s", args[1].c_str(),
389              args[2].c_str());
390     }
391
392     return NO_ERROR;
393 }
394
395 status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
396     const int argCount = args.size();
397     if (argCount >= 2) {
398         if (args[1] == "update" || args[1] == "remove") {
399             bool good = false;
400             int uid = -1;
401             string name;
402
403             if (argCount == 3) {
404                 // Automatically pick the UID
405                 uid = IPCThreadState::self()->getCallingUid();
406                 // TODO: What if this isn't a binder call? Should we fail?
407                 name.assign(args[2].c_str(), args[2].size());
408                 good = true;
409             } else if (argCount == 4) {
410                 // If it's a userdebug or eng build, then the shell user can
411                 // impersonate other uids.
412                 if (mEngBuild) {
413                     const char* s = args[2].c_str();
414                     if (*s != '\0') {
415                         char* end = NULL;
416                         uid = strtol(s, &end, 0);
417                         if (*end == '\0') {
418                             name.assign(args[3].c_str(), args[3].size());
419                             good = true;
420                         }
421                     }
422                 } else {
423                     fprintf(err,
424                             "The config can only be set for other UIDs on eng or userdebug "
425                             "builds.\n");
426                 }
427             } else if (argCount == 2 && args[1] == "remove") {
428                 good = true;
429             }
430
431             if (!good) {
432                 // If arg parsing failed, print the help text and return an error.
433                 print_cmd_help(out);
434                 return UNKNOWN_ERROR;
435             }
436
437             if (args[1] == "update") {
438                 char* endp;
439                 int64_t configID = strtoll(name.c_str(), &endp, 10);
440                 if (endp == name.c_str() || *endp != '\0') {
441                     fprintf(err, "Error parsing config ID.\n");
442                     return UNKNOWN_ERROR;
443                 }
444
445                 // Read stream into buffer.
446                 string buffer;
447                 if (!android::base::ReadFdToString(fileno(in), &buffer)) {
448                     fprintf(err, "Error reading stream for StatsConfig.\n");
449                     return UNKNOWN_ERROR;
450                 }
451
452                 // Parse buffer.
453                 StatsdConfig config;
454                 if (!config.ParseFromString(buffer)) {
455                     fprintf(err, "Error parsing proto stream for StatsConfig.\n");
456                     return UNKNOWN_ERROR;
457                 }
458
459                 // Add / update the config.
460                 mConfigManager->UpdateConfig(ConfigKey(uid, configID), config);
461             } else {
462                 if (argCount == 2) {
463                     cmd_remove_all_configs(out);
464                 } else {
465                     // Remove the config.
466                     mConfigManager->RemoveConfig(ConfigKey(uid, StrToInt64(name)));
467                 }
468             }
469
470             return NO_ERROR;
471         }
472     }
473     print_cmd_help(out);
474     return UNKNOWN_ERROR;
475 }
476
477 status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args) {
478     if (mProcessor != nullptr) {
479         int argCount = args.size();
480         bool good = false;
481         bool proto = false;
482         int uid;
483         string name;
484         if (!std::strcmp("--proto", args[argCount-1].c_str())) {
485             proto = true;
486             argCount -= 1;
487         }
488         if (argCount == 2) {
489             // Automatically pick the UID
490             uid = IPCThreadState::self()->getCallingUid();
491             // TODO: What if this isn't a binder call? Should we fail?
492             name.assign(args[1].c_str(), args[1].size());
493             good = true;
494         } else if (argCount == 3) {
495             // If it's a userdebug or eng build, then the shell user can
496             // impersonate other uids.
497             if (mEngBuild) {
498                 const char* s = args[1].c_str();
499                 if (*s != '\0') {
500                     char* end = NULL;
501                     uid = strtol(s, &end, 0);
502                     if (*end == '\0') {
503                         name.assign(args[2].c_str(), args[2].size());
504                         good = true;
505                     }
506                 }
507             } else {
508                 fprintf(out,
509                         "The metrics can only be dumped for other UIDs on eng or userdebug "
510                         "builds.\n");
511             }
512         }
513         if (good) {
514             vector<uint8_t> data;
515             mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
516                                      false /* include_current_bucket*/, &data);
517             // TODO: print the returned StatsLogReport to file instead of printing to logcat.
518             if (proto) {
519                 for (size_t i = 0; i < data.size(); i ++) {
520                     fprintf(out, "%c", data[i]);
521                 }
522             } else {
523                 fprintf(out, "Dump report for Config [%d,%s]\n", uid, name.c_str());
524                 fprintf(out, "See the StatsLogReport in logcat...\n");
525             }
526             return android::OK;
527         } else {
528             // If arg parsing failed, print the help text and return an error.
529             print_cmd_help(out);
530             return UNKNOWN_ERROR;
531         }
532     } else {
533         fprintf(out, "Log processor does not exist...\n");
534         return UNKNOWN_ERROR;
535     }
536 }
537
538 status_t StatsService::cmd_print_stats(FILE* out, const Vector<String8>& args) {
539     int argCount = args.size();
540     bool proto = false;
541     if (!std::strcmp("--proto", args[argCount-1].c_str())) {
542         proto = true;
543         argCount -= 1;
544     }
545     StatsdStats& statsdStats = StatsdStats::getInstance();
546     if (proto) {
547         vector<uint8_t> data;
548         statsdStats.dumpStats(&data, false); // does not reset statsdStats.
549         for (size_t i = 0; i < data.size(); i ++) {
550             fprintf(out, "%c", data[i]);
551         }
552
553     } else {
554         vector<ConfigKey> configs = mConfigManager->GetAllConfigKeys();
555         for (const ConfigKey& key : configs) {
556             fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
557                     mProcessor->GetMetricsSize(key));
558         }
559         statsdStats.dumpStats(out);
560     }
561     return NO_ERROR;
562 }
563
564 status_t StatsService::cmd_print_uid_map(FILE* out, const Vector<String8>& args) {
565     if (args.size() > 1) {
566         string pkg;
567         pkg.assign(args[1].c_str(), args[1].size());
568         auto uids = mUidMap->getAppUid(pkg);
569         fprintf(out, "%s -> [ ", pkg.c_str());
570         for (const auto& uid : uids) {
571             fprintf(out, "%d ", uid);
572         }
573         fprintf(out, "]\n");
574     } else {
575         mUidMap->printUidMap(out);
576     }
577     return NO_ERROR;
578 }
579
580 status_t StatsService::cmd_write_data_to_disk(FILE* out) {
581     fprintf(out, "Writing data to disk\n");
582     mProcessor->WriteDataToDisk();
583     return NO_ERROR;
584 }
585
586 status_t StatsService::cmd_log_app_breadcrumb(FILE* out, const Vector<String8>& args) {
587     bool good = false;
588     int32_t uid;
589     int32_t label;
590     int32_t state;
591     const int argCount = args.size();
592     if (argCount == 3) {
593         // Automatically pick the UID
594         uid = IPCThreadState::self()->getCallingUid();
595         label = atoi(args[1].c_str());
596         state = atoi(args[2].c_str());
597         good = true;
598     } else if (argCount == 4) {
599         uid = atoi(args[1].c_str());
600         // If it's a userdebug or eng build, then the shell user can impersonate other uids.
601         // Otherwise, the uid must match the actual caller's uid.
602         if (mEngBuild || (uid >= 0 && (uid_t)uid == IPCThreadState::self()->getCallingUid())) {
603             label = atoi(args[2].c_str());
604             state = atoi(args[3].c_str());
605             good = true;
606         } else {
607             fprintf(out,
608                     "Selecting a UID for writing AppBreadcrumb can only be done for other UIDs "
609                             "on eng or userdebug builds.\n");
610         }
611     }
612     if (good) {
613         fprintf(out, "Logging AppBreadcrumbReported(%d, %d, %d) to statslog.\n", uid, label, state);
614         android::util::stats_write(android::util::APP_BREADCRUMB_REPORTED, uid, label, state);
615     } else {
616         print_cmd_help(out);
617         return UNKNOWN_ERROR;
618     }
619     return NO_ERROR;
620 }
621
622 status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) {
623     int s = atoi(args[1].c_str());
624     vector<shared_ptr<LogEvent> > stats;
625     if (mStatsPullerManager.Pull(s, getElapsedRealtimeNs(), &stats)) {
626         for (const auto& it : stats) {
627             fprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
628         }
629         fprintf(out, "Pull from %d: Received %zu elements\n", s, stats.size());
630         return NO_ERROR;
631     }
632     return UNKNOWN_ERROR;
633 }
634
635 status_t StatsService::cmd_remove_all_configs(FILE* out) {
636     fprintf(out, "Removing all configs...\n");
637     VLOG("StatsService::cmd_remove_all_configs was called");
638     mConfigManager->RemoveAllConfigs();
639     StorageManager::deleteAllFiles(STATS_SERVICE_DIR);
640     return NO_ERROR;
641 }
642
643 status_t StatsService::cmd_dump_memory_info(FILE* out) {
644     fprintf(out, "meminfo not available.\n");
645     return NO_ERROR;
646 }
647
648 status_t StatsService::cmd_clear_puller_cache(FILE* out) {
649     IPCThreadState* ipc = IPCThreadState::self();
650     VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i",
651             ipc->getCallingPid(), ipc->getCallingUid());
652     if (checkCallingPermission(String16(kPermissionDump))) {
653         int cleared = mStatsPullerManager.ForceClearPullerCache();
654         fprintf(out, "Puller removed %d cached data!\n", cleared);
655         return NO_ERROR;
656     } else {
657         return PERMISSION_DENIED;
658     }
659 }
660
661 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
662                                       const vector<String16>& app) {
663     VLOG("StatsService::informAllUidData was called");
664
665     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
666         return Status::fromExceptionCode(Status::EX_SECURITY,
667                                          "Only system uid can call informAllUidData");
668     }
669
670     mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
671     VLOG("StatsService::informAllUidData succeeded");
672
673     return Status::ok();
674 }
675
676 Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
677     VLOG("StatsService::informOnePackage was called");
678
679     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
680         return Status::fromExceptionCode(Status::EX_SECURITY,
681                                          "Only system uid can call informOnePackage");
682     }
683     mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
684     return Status::ok();
685 }
686
687 Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
688     VLOG("StatsService::informOnePackageRemoved was called");
689
690     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
691         return Status::fromExceptionCode(Status::EX_SECURITY,
692                                          "Only system uid can call informOnePackageRemoved");
693     }
694     mUidMap->removeApp(getElapsedRealtimeNs(), app, uid);
695     mConfigManager->RemoveConfigs(uid);
696     return Status::ok();
697 }
698
699 Status StatsService::informAnomalyAlarmFired() {
700     VLOG("StatsService::informAnomalyAlarmFired was called");
701
702     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
703         return Status::fromExceptionCode(Status::EX_SECURITY,
704                                          "Only system uid can call informAnomalyAlarmFired");
705     }
706
707     int64_t currentTimeSec = getElapsedRealtimeSec();
708     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
709             mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
710     if (alarmSet.size() > 0) {
711         VLOG("Found an anomaly alarm that fired.");
712         mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
713     } else {
714         VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
715     }
716     return Status::ok();
717 }
718
719 Status StatsService::informAlarmForSubscriberTriggeringFired() {
720     VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
721
722     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
723         return Status::fromExceptionCode(
724                 Status::EX_SECURITY,
725                 "Only system uid can call informAlarmForSubscriberTriggeringFired");
726     }
727
728     int64_t currentTimeSec = getElapsedRealtimeSec();
729     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
730             mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
731     if (alarmSet.size() > 0) {
732         VLOG("Found periodic alarm fired.");
733         mProcessor->onPeriodicAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
734     } else {
735         ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
736     }
737     return Status::ok();
738 }
739
740 Status StatsService::informPollAlarmFired() {
741     VLOG("StatsService::informPollAlarmFired was called");
742
743     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
744         return Status::fromExceptionCode(Status::EX_SECURITY,
745                                          "Only system uid can call informPollAlarmFired");
746     }
747
748     mProcessor->informPullAlarmFired(getElapsedRealtimeNs());
749
750     VLOG("StatsService::informPollAlarmFired succeeded");
751
752     return Status::ok();
753 }
754
755 Status StatsService::systemRunning() {
756     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
757         return Status::fromExceptionCode(Status::EX_SECURITY,
758                                          "Only system uid can call systemRunning");
759     }
760
761     // When system_server is up and running, schedule the dropbox task to run.
762     VLOG("StatsService::systemRunning");
763
764     sayHiToStatsCompanion();
765
766     return Status::ok();
767 }
768
769 Status StatsService::writeDataToDisk() {
770     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
771         return Status::fromExceptionCode(Status::EX_SECURITY,
772                                          "Only system uid can call systemRunning");
773     }
774
775     VLOG("StatsService::writeDataToDisk");
776
777     mProcessor->WriteDataToDisk();
778
779     return Status::ok();
780 }
781
782 void StatsService::sayHiToStatsCompanion() {
783     sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
784     if (statsCompanion != nullptr) {
785         VLOG("Telling statsCompanion that statsd is ready");
786         statsCompanion->statsdReady();
787     } else {
788         VLOG("Could not access statsCompanion");
789     }
790 }
791
792 Status StatsService::statsCompanionReady() {
793     VLOG("StatsService::statsCompanionReady was called");
794
795     if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
796         return Status::fromExceptionCode(Status::EX_SECURITY,
797                                          "Only system uid can call statsCompanionReady");
798     }
799
800     sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
801     if (statsCompanion == nullptr) {
802         return Status::fromExceptionCode(
803                 Status::EX_NULL_POINTER,
804                 "statscompanion unavailable despite it contacting statsd!");
805     }
806     VLOG("StatsService::statsCompanionReady linking to statsCompanion.");
807     IInterface::asBinder(statsCompanion)->linkToDeath(this);
808     mStatsPullerManager.SetStatsCompanionService(statsCompanion);
809     mAnomalyAlarmMonitor->setStatsCompanionService(statsCompanion);
810     mPeriodicAlarmMonitor->setStatsCompanionService(statsCompanion);
811     SubscriberReporter::getInstance().setStatsCompanionService(statsCompanion);
812     return Status::ok();
813 }
814
815 void StatsService::Startup() {
816     mConfigManager->Startup();
817 }
818
819 void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) {
820     mProcessor->OnLogEvent(event, reconnectionStarts);
821 }
822
823 Status StatsService::getData(int64_t key, vector<uint8_t>* output) {
824     IPCThreadState* ipc = IPCThreadState::self();
825     VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
826     if (!checkCallingPermission(String16(kPermissionDump))) {
827         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
828     }
829     ConfigKey configKey(ipc->getCallingUid(), key);
830     mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
831                              false /* include_current_bucket*/, output);
832     return Status::ok();
833 }
834
835 Status StatsService::getMetadata(vector<uint8_t>* output) {
836     IPCThreadState* ipc = IPCThreadState::self();
837     VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(),
838          ipc->getCallingUid());
839     if (!checkCallingPermission(String16(kPermissionDump))) {
840         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
841     }
842     StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters.
843     return Status::ok();
844 }
845
846 Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config) {
847     if (!checkCallingPermission(String16(kPermissionDump))) {
848         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
849     }
850     IPCThreadState* ipc = IPCThreadState::self();
851     if (addConfigurationChecked(ipc->getCallingUid(), key, config)) {
852         return Status::ok();
853     } else {
854         ALOGE("Could not parse malformatted StatsdConfig");
855         return Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT,
856                                          "config does not correspond to a StatsdConfig proto");
857     }
858 }
859
860 bool StatsService::addConfigurationChecked(int uid, int64_t key, const vector<uint8_t>& config) {
861     ConfigKey configKey(uid, key);
862     StatsdConfig cfg;
863     if (config.size() > 0) {  // If the config is empty, skip parsing.
864         if (!cfg.ParseFromArray(&config[0], config.size())) {
865             return false;
866         }
867     }
868     mConfigManager->UpdateConfig(configKey, cfg);
869     return true;
870 }
871
872 Status StatsService::removeDataFetchOperation(int64_t key) {
873     if (!checkCallingPermission(String16(kPermissionDump))) {
874         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
875     }
876     IPCThreadState* ipc = IPCThreadState::self();
877     ConfigKey configKey(ipc->getCallingUid(), key);
878     mConfigManager->RemoveConfigReceiver(configKey);
879     return Status::ok();
880 }
881
882 Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender) {
883     if (!checkCallingPermission(String16(kPermissionDump))) {
884         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
885     }
886     IPCThreadState* ipc = IPCThreadState::self();
887     ConfigKey configKey(ipc->getCallingUid(), key);
888     mConfigManager->SetConfigReceiver(configKey, intentSender);
889     return Status::ok();
890 }
891
892 Status StatsService::removeConfiguration(int64_t key) {
893     if (!checkCallingPermission(String16(kPermissionDump))) {
894         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
895     }
896     IPCThreadState* ipc = IPCThreadState::self();
897     ConfigKey configKey(ipc->getCallingUid(), key);
898     mConfigManager->RemoveConfig(configKey);
899     SubscriberReporter::getInstance().removeConfig(configKey);
900     return Status::ok();
901 }
902
903 Status StatsService::setBroadcastSubscriber(int64_t configId,
904                                             int64_t subscriberId,
905                                             const sp<android::IBinder>& intentSender) {
906     VLOG("StatsService::setBroadcastSubscriber called.");
907     if (!checkCallingPermission(String16(kPermissionDump))) {
908         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
909     }
910     IPCThreadState* ipc = IPCThreadState::self();
911     ConfigKey configKey(ipc->getCallingUid(), configId);
912     SubscriberReporter::getInstance()
913             .setBroadcastSubscriber(configKey, subscriberId, intentSender);
914     return Status::ok();
915 }
916
917 Status StatsService::unsetBroadcastSubscriber(int64_t configId,
918                                               int64_t subscriberId) {
919     VLOG("StatsService::unsetBroadcastSubscriber called.");
920     if (!checkCallingPermission(String16(kPermissionDump))) {
921         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
922     }
923     IPCThreadState* ipc = IPCThreadState::self();
924     ConfigKey configKey(ipc->getCallingUid(), configId);
925     SubscriberReporter::getInstance()
926             .unsetBroadcastSubscriber(configKey, subscriberId);
927     return Status::ok();
928 }
929
930
931 void StatsService::binderDied(const wp <IBinder>& who) {
932     ALOGW("statscompanion service died");
933     mProcessor->WriteDataToDisk();
934     mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
935     mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
936     SubscriberReporter::getInstance().setStatsCompanionService(nullptr);
937     mStatsPullerManager.SetStatsCompanionService(nullptr);
938 }
939
940 }  // namespace statsd
941 }  // namespace os
942 }  // namespace android