blob: b496404962d5b086bd12fbaf13e0d6d94d91805a [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
17#define LOG_TAG "statsd"
Bookatzb487b552017-09-18 11:26:01 -070018#define DEBUG true
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070019
20#include "StatsService.h"
Yao Chen482d2722017-09-12 13:25:43 -070021#include "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>
26#include <cutils/log.h>
David Chen0656b7a2017-09-13 15:53:39 -070027#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070028#include <private/android_filesystem_config.h>
29#include <utils/Looper.h>
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070030#include <utils/String16.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070031
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070032#include <stdio.h>
Yao Chen482d2722017-09-12 13:25:43 -070033#include <stdlib.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 Onorato5dcbc6c2017-08-29 15:13:58 -070042StatsService::StatsService(const sp<Looper>& handlerLooper)
David Chende701692017-10-05 13:16:02 -070043 : mAnomalyMonitor(new AnomalyMonitor(2)),m_UidMap(new UidMap()), mStatsPullerManager()
44 // TODO: Change AnomalyMonitor initialization based on the config
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070045{
46 ALOGD("stats service constructed");
47}
48
Yao Chenef99c4f2017-09-22 16:26:54 -070049StatsService::~StatsService() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070050}
51
Yao Chenef99c4f2017-09-22 16:26:54 -070052status_t StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) {
David Chen0656b7a2017-09-13 15:53:39 -070053 m_processor = main_processor;
54 ALOGD("stats service set to processor %p", m_processor.get());
55 return NO_ERROR;
56}
57
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070058// Implement our own because the default binder implementation isn't
59// properly handling SHELL_COMMAND_TRANSACTION
Yao Chenef99c4f2017-09-22 16:26:54 -070060status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
61 uint32_t flags) {
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070062 status_t err;
63
64 switch (code) {
65 case SHELL_COMMAND_TRANSACTION: {
66 int in = data.readFileDescriptor();
67 int out = data.readFileDescriptor();
68 int err = data.readFileDescriptor();
69 int argc = data.readInt32();
70 Vector<String8> args;
71 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
72 args.add(String8(data.readString16()));
73 }
Yao Chenef99c4f2017-09-22 16:26:54 -070074 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
75 sp<IResultReceiver> resultReceiver =
76 IResultReceiver::asInterface(data.readStrongBinder());
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070077
78 FILE* fin = fdopen(in, "r");
79 FILE* fout = fdopen(out, "w");
80 FILE* ferr = fdopen(err, "w");
81
82 if (fin == NULL || fout == NULL || ferr == NULL) {
83 resultReceiver->send(NO_MEMORY);
84 } else {
85 err = command(fin, fout, ferr, args);
86 resultReceiver->send(err);
87 }
88
89 if (fin != NULL) {
90 fflush(fin);
91 fclose(fin);
92 }
93 if (fout != NULL) {
94 fflush(fout);
95 fclose(fout);
96 }
97 if (fout != NULL) {
98 fflush(ferr);
99 fclose(ferr);
100 }
101
102 return NO_ERROR;
103 }
Yao Chenef99c4f2017-09-22 16:26:54 -0700104 default: { return BnStatsManager::onTransact(code, data, reply, flags); }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700105 }
106}
107
Yao Chenef99c4f2017-09-22 16:26:54 -0700108status_t StatsService::dump(int fd, const Vector<String16>& args) {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700109 FILE* out = fdopen(fd, "w");
110 if (out == NULL) {
111 return NO_MEMORY; // the fd is already open
112 }
113
114 fprintf(out, "StatsService::dump:");
115 ALOGD("StatsService::dump:");
116 const int N = args.size();
Yao Chenef99c4f2017-09-22 16:26:54 -0700117 for (int i = 0; i < N; i++) {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700118 fprintf(out, " %s", String8(args[i]).string());
119 ALOGD(" %s", String8(args[i]).string());
120 }
121 fprintf(out, "\n");
122
123 fclose(out);
124 return NO_ERROR;
125}
126
Yao Chenef99c4f2017-09-22 16:26:54 -0700127status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
Yao Chen482d2722017-09-12 13:25:43 -0700128 if (args.size() > 0) {
129 if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
130 return doPrintStatsLog(out, args);
131 }
David Chen0656b7a2017-09-13 15:53:39 -0700132 if (!args[0].compare(String8("config"))) {
133 return doLoadConfig(in);
134 }
David Chende701692017-10-05 13:16:02 -0700135 if (!args[0].compare(String8("print-uid-map"))) {
136 return doPrintUidMap(out);
137 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700138 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700139
Yao Chen482d2722017-09-12 13:25:43 -0700140 printCmdHelp(out);
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700141 return NO_ERROR;
142}
143
Yao Chenef99c4f2017-09-22 16:26:54 -0700144status_t StatsService::doLoadConfig(FILE* in) {
David Chen0656b7a2017-09-13 15:53:39 -0700145 string content;
146 if (!android::base::ReadFdToString(fileno(in), &content)) {
147 return UNKNOWN_ERROR;
148 }
149 StatsdConfig config;
150 if (config.ParseFromString(content)) {
151 ALOGD("Config parsed from command line: %s", config.SerializeAsString().c_str());
152 m_processor->UpdateConfig(0, config);
153 return NO_ERROR;
154 } else {
155 ALOGD("Config failed to be parsed");
156 return UNKNOWN_ERROR;
157 }
158}
159
David Chende701692017-10-05 13:16:02 -0700160Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
161 const vector<String16>& app) {
162 if (DEBUG) ALOGD("StatsService::informAllUidData was called");
163
164 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
165 return Status::fromExceptionCode(Status::EX_SECURITY,
166 "Only system uid can call informAllUidData");
167 }
168
169 m_UidMap->updateMap(uid, version, app);
170 if (DEBUG) ALOGD("StatsService::informAllUidData succeeded");
171
172 return Status::ok();
173}
174
175Status StatsService::informOnePackage(const String16& app, int32_t uid, int32_t version) {
176 if (DEBUG) ALOGD("StatsService::informOnePackage was called");
177
178 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
179 return Status::fromExceptionCode(Status::EX_SECURITY,
180 "Only system uid can call informOnePackage");
181 }
182 m_UidMap->updateApp(app, uid, version);
183 return Status::ok();
184}
185
186Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
187 if (DEBUG) ALOGD("StatsService::informOnePackageRemoved was called");
188
189 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
190 return Status::fromExceptionCode(Status::EX_SECURITY,
191 "Only system uid can call informOnePackageRemoved");
192 }
193 m_UidMap->removeApp(app, uid);
194 return Status::ok();
195}
196
Yao Chenef99c4f2017-09-22 16:26:54 -0700197Status StatsService::informAnomalyAlarmFired() {
Bookatzb487b552017-09-18 11:26:01 -0700198 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700199
200 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
201 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700202 "Only system uid can call informAnomalyAlarmFired");
Bookatz1b0b1142017-09-08 11:58:42 -0700203 }
204
Bookatzb487b552017-09-18 11:26:01 -0700205 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700206 // TODO: check through all counters/timers and see if an anomaly has indeed occurred.
207
208 return Status::ok();
209}
210
Yao Chenef99c4f2017-09-22 16:26:54 -0700211Status StatsService::informPollAlarmFired() {
Bookatzb487b552017-09-18 11:26:01 -0700212 if (DEBUG) ALOGD("StatsService::informPollAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700213
214 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
215 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700216 "Only system uid can call informPollAlarmFired");
Bookatz1b0b1142017-09-08 11:58:42 -0700217 }
218
Bookatzb487b552017-09-18 11:26:01 -0700219 if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700220 // TODO: determine what services to poll and poll (or ask StatsCompanionService to poll) them.
Chenjie Yu1a317ba2017-10-05 16:05:32 -0700221 String16 output = mStatsPullerManager.pull(StatsPullerManager::KERNEL_WAKELOCKS);
Bookatzc68a9d22017-09-27 14:09:55 -0700222 // TODO: do something useful with the output instead of writing a string to screen.
223 ALOGD("%s", String8(output).string());
Chenjie Yu1a317ba2017-10-05 16:05:32 -0700224 ALOGD("%d", int(output.size()));
Bookatz1b0b1142017-09-08 11:58:42 -0700225
226 return Status::ok();
227}
228
Yao Chenef99c4f2017-09-22 16:26:54 -0700229Status StatsService::systemRunning() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700230 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
231 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700232 "Only system uid can call systemRunning");
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700233 }
234
235 // When system_server is up and running, schedule the dropbox task to run.
236 ALOGD("StatsService::systemRunning");
237
Bookatzb487b552017-09-18 11:26:01 -0700238 sayHiToStatsCompanion();
239
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700240 return Status::ok();
241}
242
Yao Chenef99c4f2017-09-22 16:26:54 -0700243void StatsService::sayHiToStatsCompanion() {
244 // TODO: This method needs to be private. It is temporarily public and unsecured for testing
245 // purposes.
Bookatzb487b552017-09-18 11:26:01 -0700246 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
247 if (statsCompanion != nullptr) {
248 if (DEBUG) ALOGD("Telling statsCompanion that statsd is ready");
249 statsCompanion->statsdReady();
250 } else {
251 if (DEBUG) ALOGD("Could not access statsCompanion");
252 }
253}
254
Yao Chenef99c4f2017-09-22 16:26:54 -0700255sp<IStatsCompanionService> StatsService::getStatsCompanionService() {
Bookatz906a35c2017-09-20 15:26:44 -0700256 sp<IStatsCompanionService> statsCompanion = nullptr;
257 // Get statscompanion service from service manager
258 const sp<IServiceManager> sm(defaultServiceManager());
259 if (sm != nullptr) {
260 const String16 name("statscompanion");
261 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
262 if (statsCompanion == nullptr) {
263 ALOGW("statscompanion service unavailable!");
264 return nullptr;
265 }
266 }
267 return statsCompanion;
268}
269
Yao Chenef99c4f2017-09-22 16:26:54 -0700270Status StatsService::statsCompanionReady() {
Bookatzb487b552017-09-18 11:26:01 -0700271 if (DEBUG) ALOGD("StatsService::statsCompanionReady was called");
272
273 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
274 return Status::fromExceptionCode(Status::EX_SECURITY,
275 "Only system uid can call statsCompanionReady");
276 }
277
278 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
279 if (statsCompanion == nullptr) {
Yao Chenef99c4f2017-09-22 16:26:54 -0700280 return Status::fromExceptionCode(
281 Status::EX_NULL_POINTER,
282 "statscompanion unavailable despite it contacting statsd!");
Bookatzb487b552017-09-18 11:26:01 -0700283 }
284 if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion.");
285 IInterface::asBinder(statsCompanion)->linkToDeath(new StatsdDeathRecipient(mAnomalyMonitor));
286 mAnomalyMonitor->setStatsCompanionService(statsCompanion);
287
288 return Status::ok();
289}
290
Yao Chenef99c4f2017-09-22 16:26:54 -0700291void StatsdDeathRecipient::binderDied(const wp<IBinder>& who) {
Bookatzb487b552017-09-18 11:26:01 -0700292 ALOGW("statscompanion service died");
293 mAnmlyMntr->setStatsCompanionService(nullptr);
Bookatz906a35c2017-09-20 15:26:44 -0700294}
295
Yao Chenef99c4f2017-09-22 16:26:54 -0700296status_t StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) {
Bookatz906a35c2017-09-20 15:26:44 -0700297 long msec = 0;
298
299 if (args.size() > 2) {
300 msec = strtol(args[2].string(), NULL, 10);
301 }
302 return DropboxReader::readStatsLogs(out, args[1].string(), msec);
303}
304
David Chende701692017-10-05 13:16:02 -0700305status_t StatsService::doPrintUidMap(FILE* out) {
306 m_UidMap->printUidMap(out);
307 return NO_ERROR;
308}
309
Yao Chenef99c4f2017-09-22 16:26:54 -0700310void StatsService::printCmdHelp(FILE* out) {
Bookatz906a35c2017-09-20 15:26:44 -0700311 fprintf(out, "Usage:\n");
312 fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n");
David Chende701692017-10-05 13:16:02 -0700313 fprintf(out, "\t print-uid-map Prints the UID, app name, version mapping.\n");
Yao Chenef99c4f2017-09-22 16:26:54 -0700314 fprintf(out,
315 "\t config\t Loads a new config from command-line (must be proto in wire-encoded "
316 "format).\n");
Bookatz906a35c2017-09-20 15:26:44 -0700317}
318
Yao Chenef99c4f2017-09-22 16:26:54 -0700319} // namespace statsd
320} // namespace os
321} // namespace android