blob: 965c9b7192de80c31617671c36c1a7f25f658fcc [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;
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)
Bookatzb487b552017-09-18 11:26:01 -070043 : mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Change this based on the config
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070044{
45 ALOGD("stats service constructed");
46}
47
48StatsService::~StatsService()
49{
50}
51
David Chen0656b7a2017-09-13 15:53:39 -070052status_t
53StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) {
54 m_processor = main_processor;
55 ALOGD("stats service set to processor %p", m_processor.get());
56 return NO_ERROR;
57}
58
Joe Onorato2cbc2cc2017-08-30 17:03:23 -070059// Implement our own because the default binder implementation isn't
60// properly handling SHELL_COMMAND_TRANSACTION
61status_t
62StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
63{
64 status_t err;
65
66 switch (code) {
67 case SHELL_COMMAND_TRANSACTION: {
68 int in = data.readFileDescriptor();
69 int out = data.readFileDescriptor();
70 int err = data.readFileDescriptor();
71 int argc = data.readInt32();
72 Vector<String8> args;
73 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
74 args.add(String8(data.readString16()));
75 }
76 sp<IShellCallback> shellCallback = IShellCallback::asInterface(
77 data.readStrongBinder());
78 sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
79 data.readStrongBinder());
80
81 FILE* fin = fdopen(in, "r");
82 FILE* fout = fdopen(out, "w");
83 FILE* ferr = fdopen(err, "w");
84
85 if (fin == NULL || fout == NULL || ferr == NULL) {
86 resultReceiver->send(NO_MEMORY);
87 } else {
88 err = command(fin, fout, ferr, args);
89 resultReceiver->send(err);
90 }
91
92 if (fin != NULL) {
93 fflush(fin);
94 fclose(fin);
95 }
96 if (fout != NULL) {
97 fflush(fout);
98 fclose(fout);
99 }
100 if (fout != NULL) {
101 fflush(ferr);
102 fclose(ferr);
103 }
104
105 return NO_ERROR;
106 }
107 default: {
108 return BnStatsManager::onTransact(code, data, reply, flags);
109 }
110 }
111}
112
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700113status_t
114StatsService::dump(int fd, const Vector<String16>& args)
115{
116 FILE* out = fdopen(fd, "w");
117 if (out == NULL) {
118 return NO_MEMORY; // the fd is already open
119 }
120
121 fprintf(out, "StatsService::dump:");
122 ALOGD("StatsService::dump:");
123 const int N = args.size();
124 for (int i=0; i<N; i++) {
125 fprintf(out, " %s", String8(args[i]).string());
126 ALOGD(" %s", String8(args[i]).string());
127 }
128 fprintf(out, "\n");
129
130 fclose(out);
131 return NO_ERROR;
132}
133
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700134status_t
135StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args)
136{
Yao Chen482d2722017-09-12 13:25:43 -0700137 if (args.size() > 0) {
138 if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
139 return doPrintStatsLog(out, args);
140 }
David Chen0656b7a2017-09-13 15:53:39 -0700141 if (!args[0].compare(String8("config"))) {
142 return doLoadConfig(in);
143 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700144 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700145
Yao Chen482d2722017-09-12 13:25:43 -0700146 printCmdHelp(out);
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700147 return NO_ERROR;
148}
149
David Chen0656b7a2017-09-13 15:53:39 -0700150status_t
151StatsService::doLoadConfig(FILE* in)
152{
153 string content;
154 if (!android::base::ReadFdToString(fileno(in), &content)) {
155 return UNKNOWN_ERROR;
156 }
157 StatsdConfig config;
158 if (config.ParseFromString(content)) {
159 ALOGD("Config parsed from command line: %s", config.SerializeAsString().c_str());
160 m_processor->UpdateConfig(0, config);
161 return NO_ERROR;
162 } else {
163 ALOGD("Config failed to be parsed");
164 return UNKNOWN_ERROR;
165 }
166}
167
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700168Status
Bookatz1b0b1142017-09-08 11:58:42 -0700169StatsService::informAnomalyAlarmFired()
170{
Bookatzb487b552017-09-18 11:26:01 -0700171 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700172
173 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
174 return Status::fromExceptionCode(Status::EX_SECURITY,
175 "Only system uid can call informAnomalyAlarmFired");
176 }
177
Bookatzb487b552017-09-18 11:26:01 -0700178 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700179 // TODO: check through all counters/timers and see if an anomaly has indeed occurred.
180
181 return Status::ok();
182}
183
184Status
185StatsService::informPollAlarmFired()
186{
Bookatzb487b552017-09-18 11:26:01 -0700187 if (DEBUG) ALOGD("StatsService::informPollAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700188
189 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
190 return Status::fromExceptionCode(Status::EX_SECURITY,
191 "Only system uid can call informPollAlarmFired");
192 }
193
Bookatzb487b552017-09-18 11:26:01 -0700194 if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700195 // TODO: determine what services to poll and poll (or ask StatsCompanionService to poll) them.
196
197 return Status::ok();
198}
199
200Status
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700201StatsService::systemRunning()
202{
203 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
204 return Status::fromExceptionCode(Status::EX_SECURITY,
205 "Only system uid can call systemRunning");
206 }
207
208 // When system_server is up and running, schedule the dropbox task to run.
209 ALOGD("StatsService::systemRunning");
210
Bookatzb487b552017-09-18 11:26:01 -0700211 sayHiToStatsCompanion();
212
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700213 return Status::ok();
214}
215
Bookatzb487b552017-09-18 11:26:01 -0700216void
217StatsService::sayHiToStatsCompanion()
218{
219 // TODO: This method needs to be private. It is temporarily public and unsecured for testing purposes.
220 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
221 if (statsCompanion != nullptr) {
222 if (DEBUG) ALOGD("Telling statsCompanion that statsd is ready");
223 statsCompanion->statsdReady();
224 } else {
225 if (DEBUG) ALOGD("Could not access statsCompanion");
226 }
227}
228
Bookatz906a35c2017-09-20 15:26:44 -0700229sp<IStatsCompanionService>
230StatsService::getStatsCompanionService() {
231 sp<IStatsCompanionService> statsCompanion = nullptr;
232 // Get statscompanion service from service manager
233 const sp<IServiceManager> sm(defaultServiceManager());
234 if (sm != nullptr) {
235 const String16 name("statscompanion");
236 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
237 if (statsCompanion == nullptr) {
238 ALOGW("statscompanion service unavailable!");
239 return nullptr;
240 }
241 }
242 return statsCompanion;
243}
244
Bookatzb487b552017-09-18 11:26:01 -0700245Status
246StatsService::statsCompanionReady()
247{
248 if (DEBUG) ALOGD("StatsService::statsCompanionReady was called");
249
250 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
251 return Status::fromExceptionCode(Status::EX_SECURITY,
252 "Only system uid can call statsCompanionReady");
253 }
254
255 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
256 if (statsCompanion == nullptr) {
257 return Status::fromExceptionCode(Status::EX_NULL_POINTER,
258 "statscompanion unavailable despite it contacting statsd!");
259 }
260 if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion.");
261 IInterface::asBinder(statsCompanion)->linkToDeath(new StatsdDeathRecipient(mAnomalyMonitor));
262 mAnomalyMonitor->setStatsCompanionService(statsCompanion);
263
264 return Status::ok();
265}
266
Bookatzb487b552017-09-18 11:26:01 -0700267void
268StatsdDeathRecipient::binderDied(const wp<IBinder>& who) {
269 ALOGW("statscompanion service died");
270 mAnmlyMntr->setStatsCompanionService(nullptr);
Bookatz906a35c2017-09-20 15:26:44 -0700271}
272
273status_t
274StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) {
275 long msec = 0;
276
277 if (args.size() > 2) {
278 msec = strtol(args[2].string(), NULL, 10);
279 }
280 return DropboxReader::readStatsLogs(out, args[1].string(), msec);
281}
282
283void
284StatsService::printCmdHelp(FILE* out) {
285 fprintf(out, "Usage:\n");
286 fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n");
287 fprintf(out, "\t config\t Loads a new config from command-line (must be proto in wire-encoded format).\n");
288}
289
290} // namespace statsd
291} // namespace os
292} // namespace android