blob: eff2c1cfbcec5a5e04f832b5f73e0e2755ba1a6e [file] [log] [blame]
Joe Onorato5dcbc6c2017-08-29 15:13:58 -07001/*
2 * Copyright (C) 2016 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
Bookatzb487b552017-09-18 11:26:01 -070017#define DEBUG true
Joe Onorato9fc9edf2017-10-15 20:08:52 -070018#include "Log.h"
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070019
20#include "StatsService.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070021#include "storage/DropboxReader.h"
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070022
David Chen0656b7a2017-09-13 15:53:39 -070023#include <android-base/file.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070024#include <binder/IPCThreadState.h>
25#include <binder/IServiceManager.h>
David Chen0656b7a2017-09-13 15:53:39 -070026#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070027#include <private/android_filesystem_config.h>
28#include <utils/Looper.h>
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070029#include <utils/String16.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070030
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070031#include <stdio.h>
Yao Chen482d2722017-09-12 13:25:43 -070032#include <stdlib.h>
Joe Onorato9fc9edf2017-10-15 20:08:52 -070033#include <sys/system_properties.h>
Yao Chenef99c4f2017-09-22 16:26:54 -070034#include <unistd.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070035
36using namespace android;
37
Bookatz906a35c2017-09-20 15:26:44 -070038namespace android {
39namespace os {
40namespace statsd {
41
Joe Onorato9fc9edf2017-10-15 20:08:52 -070042// ======================================================================
43/**
44 * Watches for the death of the stats companion (system process).
45 */
46class CompanionDeathRecipient : public IBinder::DeathRecipient {
47public:
48 CompanionDeathRecipient(const sp<AnomalyMonitor>& anomalyMonitor);
49 virtual void binderDied(const wp<IBinder>& who);
50
51private:
52 const sp<AnomalyMonitor> mAnomalyMonitor;
53};
54
55CompanionDeathRecipient::CompanionDeathRecipient(const sp<AnomalyMonitor>& anomalyMonitor)
56 : mAnomalyMonitor(anomalyMonitor) {
57}
58
59void CompanionDeathRecipient::binderDied(const wp<IBinder>& who) {
60 ALOGW("statscompanion service died");
61 mAnomalyMonitor->setStatsCompanionService(nullptr);
62}
63
64// ======================================================================
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070065StatsService::StatsService(const sp<Looper>& handlerLooper)
Joe Onorato9fc9edf2017-10-15 20:08:52 -070066 : mStatsPullerManager(),
67
68 mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Put this comment somewhere better
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070069{
Joe Onorato9fc9edf2017-10-15 20:08:52 -070070 mUidMap = new UidMap();
71 mConfigManager = new ConfigManager();
72 mProcessor = new StatsLogProcessor(mUidMap);
73
74 mConfigManager->AddListener(mProcessor);
75
76 init_system_properties();
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070077}
78
Yao Chenef99c4f2017-09-22 16:26:54 -070079StatsService::~StatsService() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070080}
81
Joe Onorato9fc9edf2017-10-15 20:08:52 -070082void StatsService::init_system_properties() {
83 mEngBuild = false;
84 const prop_info* buildType = __system_property_find("ro.build.type");
85 if (buildType != NULL) {
86 __system_property_read_callback(buildType, init_build_type_callback, this);
87 }
David Chen0656b7a2017-09-13 15:53:39 -070088}
89
Joe Onorato9fc9edf2017-10-15 20:08:52 -070090void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
91 uint32_t serial) {
92 if (0 == strcmp("eng", value)) {
93 reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
94 }
95}
96
97/**
98 * Implement our own because the default binder implementation isn't
99 * properly handling SHELL_COMMAND_TRANSACTION.
100 */
Yao Chenef99c4f2017-09-22 16:26:54 -0700101status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
102 uint32_t flags) {
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700103 status_t err;
104
105 switch (code) {
106 case SHELL_COMMAND_TRANSACTION: {
107 int in = data.readFileDescriptor();
108 int out = data.readFileDescriptor();
109 int err = data.readFileDescriptor();
110 int argc = data.readInt32();
111 Vector<String8> args;
112 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
113 args.add(String8(data.readString16()));
114 }
Yao Chenef99c4f2017-09-22 16:26:54 -0700115 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
116 sp<IResultReceiver> resultReceiver =
117 IResultReceiver::asInterface(data.readStrongBinder());
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700118
119 FILE* fin = fdopen(in, "r");
120 FILE* fout = fdopen(out, "w");
121 FILE* ferr = fdopen(err, "w");
122
123 if (fin == NULL || fout == NULL || ferr == NULL) {
124 resultReceiver->send(NO_MEMORY);
125 } else {
126 err = command(fin, fout, ferr, args);
127 resultReceiver->send(err);
128 }
129
130 if (fin != NULL) {
131 fflush(fin);
132 fclose(fin);
133 }
134 if (fout != NULL) {
135 fflush(fout);
136 fclose(fout);
137 }
138 if (fout != NULL) {
139 fflush(ferr);
140 fclose(ferr);
141 }
142
143 return NO_ERROR;
144 }
Yao Chenef99c4f2017-09-22 16:26:54 -0700145 default: { return BnStatsManager::onTransact(code, data, reply, flags); }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700146 }
147}
148
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700149/**
150 * Write debugging data about statsd.
151 */
Yao Chenef99c4f2017-09-22 16:26:54 -0700152status_t StatsService::dump(int fd, const Vector<String16>& args) {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700153 FILE* out = fdopen(fd, "w");
154 if (out == NULL) {
155 return NO_MEMORY; // the fd is already open
156 }
157
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700158 // TODO: Proto format for incident reports
159 dump_impl(out);
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700160
161 fclose(out);
162 return NO_ERROR;
163}
164
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700165/**
166 * Write debugging data about statsd in text format.
167 */
168void StatsService::dump_impl(FILE* out) {
169 mConfigManager->Dump(out);
170}
171
172/**
173 * Implementation of the adb shell cmd stats command.
174 */
Yao Chenef99c4f2017-09-22 16:26:54 -0700175status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700176 // TODO: Permission check
177
178 const int argCount = args.size();
179 if (argCount >= 1) {
180 // adb shell cmd stats config ...
David Chen0656b7a2017-09-13 15:53:39 -0700181 if (!args[0].compare(String8("config"))) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700182 return cmd_config(in, out, err, args);
David Chen0656b7a2017-09-13 15:53:39 -0700183 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700184
185 // adb shell cmd stats print-stats-log
186 if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
187 return cmd_print_stats_log(out, args);
188 }
189
190 // adb shell cmd stats print-stats-log
David Chende701692017-10-05 13:16:02 -0700191 if (!args[0].compare(String8("print-uid-map"))) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700192 return cmd_print_uid_map(out);
David Chende701692017-10-05 13:16:02 -0700193 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700194 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700195
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700196 print_cmd_help(out);
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700197 return NO_ERROR;
198}
199
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700200void StatsService::print_cmd_help(FILE* out) {
201 fprintf(out,
202 "usage: adb shell cmd stats print-stats-log [tag_required] "
203 "[timestamp_nsec_optional]\n");
204 fprintf(out, "\n");
205 fprintf(out, "\n");
206 fprintf(out, "usage: adb shell cmd stats print-uid-map \n");
207 fprintf(out, "\n");
208 fprintf(out, " Prints the UID, app name, version mapping.\n");
209 fprintf(out, "\n");
210 fprintf(out, "\n");
211 fprintf(out, "usage: adb shell cmd stats config remove [UID] NAME\n");
212 fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
213 fprintf(out, "\n");
214 fprintf(out, " Adds, updates or removes a configuration. The proto should be in\n");
215 fprintf(out, " wire-encoded protobuf format and passed via stdin.\n");
216 fprintf(out, "\n");
217 fprintf(out, " UID The uid to use. It is only possible to pass the UID\n");
218 fprintf(out, " parameter on eng builds. If UID is omitted the calling\n");
219 fprintf(out, " uid is used.\n");
220 fprintf(out, " NAME The per-uid name to use\n");
221}
222
223status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
224 const int argCount = args.size();
225 if (argCount >= 2) {
226 if (args[1] == "update" || args[1] == "remove") {
227 bool good = false;
228 int uid = -1;
229 string name;
230
231 if (argCount == 3) {
232 // Automatically pick the UID
233 uid = IPCThreadState::self()->getCallingUid();
234 // TODO: What if this isn't a binder call? Should we fail?
235 name.assign(args[2].c_str(), args[2].size());
236 good = true;
237 } else if (argCount == 4) {
238 // If it's a userdebug or eng build, then the shell user can
239 // impersonate other uids.
240 if (mEngBuild) {
241 const char* s = args[2].c_str();
242 if (*s != '\0') {
243 char* end = NULL;
244 uid = strtol(s, &end, 0);
245 if (*end == '\0') {
246 name.assign(args[3].c_str(), args[3].size());
247 good = true;
248 }
249 }
250 } else {
251 fprintf(err, "The config can only be set for other UIDs on eng builds.\n");
252 }
253 }
254
255 if (!good) {
256 // If arg parsing failed, print the help text and return an error.
257 print_cmd_help(out);
258 return UNKNOWN_ERROR;
259 }
260
261 if (args[1] == "update") {
262 // Read stream into buffer.
263 string buffer;
264 if (!android::base::ReadFdToString(fileno(in), &buffer)) {
265 fprintf(err, "Error reading stream for StatsConfig.\n");
266 return UNKNOWN_ERROR;
267 }
268
269 // Parse buffer.
270 StatsdConfig config;
271 if (!config.ParseFromString(buffer)) {
272 fprintf(err, "Error parsing proto stream for StatsConfig.\n");
273 return UNKNOWN_ERROR;
274 }
275
276 // Add / update the config.
277 mConfigManager->UpdateConfig(ConfigKey(uid, name), config);
278 } else {
279 // Remove the config.
280 mConfigManager->RemoveConfig(ConfigKey(uid, name));
281 }
282
283 return NO_ERROR;
284 }
David Chen0656b7a2017-09-13 15:53:39 -0700285 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700286 print_cmd_help(out);
287 return UNKNOWN_ERROR;
288}
289
290status_t StatsService::cmd_print_stats_log(FILE* out, const Vector<String8>& args) {
291 long msec = 0;
292
293 if (args.size() > 2) {
294 msec = strtol(args[2].string(), NULL, 10);
David Chen0656b7a2017-09-13 15:53:39 -0700295 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700296 return DropboxReader::readStatsLogs(out, args[1].string(), msec);
297}
298
299status_t StatsService::cmd_print_uid_map(FILE* out) {
300 mUidMap->printUidMap(out);
301 return NO_ERROR;
David Chen0656b7a2017-09-13 15:53:39 -0700302}
303
David Chende701692017-10-05 13:16:02 -0700304Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
305 const vector<String16>& app) {
306 if (DEBUG) ALOGD("StatsService::informAllUidData was called");
307
308 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
309 return Status::fromExceptionCode(Status::EX_SECURITY,
310 "Only system uid can call informAllUidData");
311 }
312
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700313 mUidMap->updateMap(uid, version, app);
David Chende701692017-10-05 13:16:02 -0700314 if (DEBUG) ALOGD("StatsService::informAllUidData succeeded");
315
316 return Status::ok();
317}
318
319Status StatsService::informOnePackage(const String16& app, int32_t uid, int32_t version) {
320 if (DEBUG) ALOGD("StatsService::informOnePackage was called");
321
322 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
323 return Status::fromExceptionCode(Status::EX_SECURITY,
324 "Only system uid can call informOnePackage");
325 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700326 mUidMap->updateApp(app, uid, version);
David Chende701692017-10-05 13:16:02 -0700327 return Status::ok();
328}
329
330Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
331 if (DEBUG) ALOGD("StatsService::informOnePackageRemoved was called");
332
333 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
334 return Status::fromExceptionCode(Status::EX_SECURITY,
335 "Only system uid can call informOnePackageRemoved");
336 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700337 mUidMap->removeApp(app, uid);
David Chende701692017-10-05 13:16:02 -0700338 return Status::ok();
339}
340
Yao Chenef99c4f2017-09-22 16:26:54 -0700341Status StatsService::informAnomalyAlarmFired() {
Bookatzb487b552017-09-18 11:26:01 -0700342 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700343
344 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
345 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700346 "Only system uid can call informAnomalyAlarmFired");
Bookatz1b0b1142017-09-08 11:58:42 -0700347 }
348
Bookatzb487b552017-09-18 11:26:01 -0700349 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700350 // TODO: check through all counters/timers and see if an anomaly has indeed occurred.
351
352 return Status::ok();
353}
354
Yao Chenef99c4f2017-09-22 16:26:54 -0700355Status StatsService::informPollAlarmFired() {
Bookatzb487b552017-09-18 11:26:01 -0700356 if (DEBUG) ALOGD("StatsService::informPollAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700357
358 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
359 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700360 "Only system uid can call informPollAlarmFired");
Bookatz1b0b1142017-09-08 11:58:42 -0700361 }
362
Bookatzb487b552017-09-18 11:26:01 -0700363 if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700364 // TODO: determine what services to poll and poll (or ask StatsCompanionService to poll) them.
Chenjie Yu1a317ba2017-10-05 16:05:32 -0700365 String16 output = mStatsPullerManager.pull(StatsPullerManager::KERNEL_WAKELOCKS);
Bookatzc68a9d22017-09-27 14:09:55 -0700366 // TODO: do something useful with the output instead of writing a string to screen.
367 ALOGD("%s", String8(output).string());
Chenjie Yu1a317ba2017-10-05 16:05:32 -0700368 ALOGD("%d", int(output.size()));
Bookatz1b0b1142017-09-08 11:58:42 -0700369
370 return Status::ok();
371}
372
Yao Chenef99c4f2017-09-22 16:26:54 -0700373Status StatsService::systemRunning() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700374 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
375 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700376 "Only system uid can call systemRunning");
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700377 }
378
379 // When system_server is up and running, schedule the dropbox task to run.
380 ALOGD("StatsService::systemRunning");
381
Bookatzb487b552017-09-18 11:26:01 -0700382 sayHiToStatsCompanion();
383
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700384 return Status::ok();
385}
386
Yao Chenef99c4f2017-09-22 16:26:54 -0700387void StatsService::sayHiToStatsCompanion() {
388 // TODO: This method needs to be private. It is temporarily public and unsecured for testing
389 // purposes.
Bookatzb487b552017-09-18 11:26:01 -0700390 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
391 if (statsCompanion != nullptr) {
392 if (DEBUG) ALOGD("Telling statsCompanion that statsd is ready");
393 statsCompanion->statsdReady();
394 } else {
395 if (DEBUG) ALOGD("Could not access statsCompanion");
396 }
397}
398
Yao Chenef99c4f2017-09-22 16:26:54 -0700399sp<IStatsCompanionService> StatsService::getStatsCompanionService() {
Bookatz906a35c2017-09-20 15:26:44 -0700400 sp<IStatsCompanionService> statsCompanion = nullptr;
401 // Get statscompanion service from service manager
402 const sp<IServiceManager> sm(defaultServiceManager());
403 if (sm != nullptr) {
404 const String16 name("statscompanion");
405 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
406 if (statsCompanion == nullptr) {
407 ALOGW("statscompanion service unavailable!");
408 return nullptr;
409 }
410 }
411 return statsCompanion;
412}
413
Yao Chenef99c4f2017-09-22 16:26:54 -0700414Status StatsService::statsCompanionReady() {
Bookatzb487b552017-09-18 11:26:01 -0700415 if (DEBUG) ALOGD("StatsService::statsCompanionReady was called");
416
417 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
418 return Status::fromExceptionCode(Status::EX_SECURITY,
419 "Only system uid can call statsCompanionReady");
420 }
421
422 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
423 if (statsCompanion == nullptr) {
Yao Chenef99c4f2017-09-22 16:26:54 -0700424 return Status::fromExceptionCode(
425 Status::EX_NULL_POINTER,
426 "statscompanion unavailable despite it contacting statsd!");
Bookatzb487b552017-09-18 11:26:01 -0700427 }
428 if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion.");
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700429 IInterface::asBinder(statsCompanion)->linkToDeath(new CompanionDeathRecipient(mAnomalyMonitor));
Bookatzb487b552017-09-18 11:26:01 -0700430 mAnomalyMonitor->setStatsCompanionService(statsCompanion);
431
432 return Status::ok();
433}
434
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700435void StatsService::Startup() {
436 mConfigManager->Startup();
Bookatz906a35c2017-09-20 15:26:44 -0700437}
438
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700439void StatsService::OnLogEvent(const log_msg& msg) {
440 mProcessor->OnLogEvent(msg);
Bookatz906a35c2017-09-20 15:26:44 -0700441}
442
Yao Chenef99c4f2017-09-22 16:26:54 -0700443} // namespace statsd
444} // namespace os
445} // namespace android