blob: 976fc26a2b8cfa0dbaf247c89bf9841dafea300a [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
32#include <unistd.h>
33#include <stdio.h>
Yao Chen482d2722017-09-12 13:25:43 -070034#include <stdlib.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070035
36using namespace android;
David Chen0656b7a2017-09-13 15:53:39 -070037using android::os::statsd::StatsdConfig;
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070038
39// ================================================================================
40StatsService::StatsService(const sp<Looper>& handlerLooper)
Bookatzb487b552017-09-18 11:26:01 -070041 : mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Change this based on the config
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070042{
43 ALOGD("stats service constructed");
44}
45
46StatsService::~StatsService()
47{
48}
49
David Chen0656b7a2017-09-13 15:53:39 -070050status_t
51StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) {
52 m_processor = main_processor;
53 ALOGD("stats service set to processor %p", m_processor.get());
54 return NO_ERROR;
55}
56
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070057// Implement our own because the default binder implementation isn't
58// properly handling SHELL_COMMAND_TRANSACTION
59status_t
60StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
61{
62 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 }
74 sp<IShellCallback> shellCallback = IShellCallback::asInterface(
75 data.readStrongBinder());
76 sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
77 data.readStrongBinder());
78
79 FILE* fin = fdopen(in, "r");
80 FILE* fout = fdopen(out, "w");
81 FILE* ferr = fdopen(err, "w");
82
83 if (fin == NULL || fout == NULL || ferr == NULL) {
84 resultReceiver->send(NO_MEMORY);
85 } else {
86 err = command(fin, fout, ferr, args);
87 resultReceiver->send(err);
88 }
89
90 if (fin != NULL) {
91 fflush(fin);
92 fclose(fin);
93 }
94 if (fout != NULL) {
95 fflush(fout);
96 fclose(fout);
97 }
98 if (fout != NULL) {
99 fflush(ferr);
100 fclose(ferr);
101 }
102
103 return NO_ERROR;
104 }
105 default: {
106 return BnStatsManager::onTransact(code, data, reply, flags);
107 }
108 }
109}
110
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700111status_t
112StatsService::dump(int fd, const Vector<String16>& args)
113{
114 FILE* out = fdopen(fd, "w");
115 if (out == NULL) {
116 return NO_MEMORY; // the fd is already open
117 }
118
119 fprintf(out, "StatsService::dump:");
120 ALOGD("StatsService::dump:");
121 const int N = args.size();
122 for (int i=0; i<N; i++) {
123 fprintf(out, " %s", String8(args[i]).string());
124 ALOGD(" %s", String8(args[i]).string());
125 }
126 fprintf(out, "\n");
127
128 fclose(out);
129 return NO_ERROR;
130}
131
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700132status_t
133StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args)
134{
Yao Chen482d2722017-09-12 13:25:43 -0700135 if (args.size() > 0) {
136 if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
137 return doPrintStatsLog(out, args);
138 }
David Chen0656b7a2017-09-13 15:53:39 -0700139 if (!args[0].compare(String8("config"))) {
140 return doLoadConfig(in);
141 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700142 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700143
Yao Chen482d2722017-09-12 13:25:43 -0700144 printCmdHelp(out);
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700145 return NO_ERROR;
146}
147
David Chen0656b7a2017-09-13 15:53:39 -0700148status_t
149StatsService::doLoadConfig(FILE* in)
150{
151 string content;
152 if (!android::base::ReadFdToString(fileno(in), &content)) {
153 return UNKNOWN_ERROR;
154 }
155 StatsdConfig config;
156 if (config.ParseFromString(content)) {
157 ALOGD("Config parsed from command line: %s", config.SerializeAsString().c_str());
158 m_processor->UpdateConfig(0, config);
159 return NO_ERROR;
160 } else {
161 ALOGD("Config failed to be parsed");
162 return UNKNOWN_ERROR;
163 }
164}
165
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700166Status
Bookatz1b0b1142017-09-08 11:58:42 -0700167StatsService::informAnomalyAlarmFired()
168{
Bookatzb487b552017-09-18 11:26:01 -0700169 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700170
171 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
172 return Status::fromExceptionCode(Status::EX_SECURITY,
173 "Only system uid can call informAnomalyAlarmFired");
174 }
175
Bookatzb487b552017-09-18 11:26:01 -0700176 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700177 // TODO: check through all counters/timers and see if an anomaly has indeed occurred.
178
179 return Status::ok();
180}
181
182Status
183StatsService::informPollAlarmFired()
184{
Bookatzb487b552017-09-18 11:26:01 -0700185 if (DEBUG) ALOGD("StatsService::informPollAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700186
187 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
188 return Status::fromExceptionCode(Status::EX_SECURITY,
189 "Only system uid can call informPollAlarmFired");
190 }
191
Bookatzb487b552017-09-18 11:26:01 -0700192 if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700193 // TODO: determine what services to poll and poll (or ask StatsCompanionService to poll) them.
194
195 return Status::ok();
196}
197
198Status
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700199StatsService::systemRunning()
200{
201 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
202 return Status::fromExceptionCode(Status::EX_SECURITY,
203 "Only system uid can call systemRunning");
204 }
205
206 // When system_server is up and running, schedule the dropbox task to run.
207 ALOGD("StatsService::systemRunning");
208
Bookatzb487b552017-09-18 11:26:01 -0700209 sayHiToStatsCompanion();
210
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700211 return Status::ok();
212}
213
Yao Chen482d2722017-09-12 13:25:43 -0700214status_t
215StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) {
216 long msec = 0;
217
218 if (args.size() > 2) {
219 msec = strtol(args[2].string(), NULL, 10);
220 }
221 return DropboxReader::readStatsLogs(out, args[1].string(), msec);
222}
223
224void
225StatsService::printCmdHelp(FILE* out) {
226 fprintf(out, "Usage:\n");
227 fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n");
David Chen0656b7a2017-09-13 15:53:39 -0700228 fprintf(out, "\t config\t Loads a new config from command-line (must be proto in wire-encoded format).\n");
Yao Chen482d2722017-09-12 13:25:43 -0700229}
Bookatzb487b552017-09-18 11:26:01 -0700230
231void
232StatsService::sayHiToStatsCompanion()
233{
234 // TODO: This method needs to be private. It is temporarily public and unsecured for testing purposes.
235 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
236 if (statsCompanion != nullptr) {
237 if (DEBUG) ALOGD("Telling statsCompanion that statsd is ready");
238 statsCompanion->statsdReady();
239 } else {
240 if (DEBUG) ALOGD("Could not access statsCompanion");
241 }
242}
243
244Status
245StatsService::statsCompanionReady()
246{
247 if (DEBUG) ALOGD("StatsService::statsCompanionReady was called");
248
249 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
250 return Status::fromExceptionCode(Status::EX_SECURITY,
251 "Only system uid can call statsCompanionReady");
252 }
253
254 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
255 if (statsCompanion == nullptr) {
256 return Status::fromExceptionCode(Status::EX_NULL_POINTER,
257 "statscompanion unavailable despite it contacting statsd!");
258 }
259 if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion.");
260 IInterface::asBinder(statsCompanion)->linkToDeath(new StatsdDeathRecipient(mAnomalyMonitor));
261 mAnomalyMonitor->setStatsCompanionService(statsCompanion);
262
263 return Status::ok();
264}
265
266sp<IStatsCompanionService>
267StatsService::getStatsCompanionService() {
268 sp<IStatsCompanionService> statsCompanion = nullptr;
269 // Get statscompanion service from service manager
270 const sp<IServiceManager> sm(defaultServiceManager());
271 if (sm != nullptr) {
272 const String16 name("statscompanion");
273 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
274 if (statsCompanion == nullptr) {
275 ALOGW("statscompanion service unavailable!");
276 return nullptr;
277 }
278 }
279 return statsCompanion;
280}
281
282void
283StatsdDeathRecipient::binderDied(const wp<IBinder>& who) {
284 ALOGW("statscompanion service died");
285 mAnmlyMntr->setStatsCompanionService(nullptr);
286}