blob: 87616d3287d6cf5884aca9a7840ff4078e807341 [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(),
Joe Onorato9fc9edf2017-10-15 20:08:52 -070067 mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Put this comment somewhere better
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070068{
Joe Onorato9fc9edf2017-10-15 20:08:52 -070069 mUidMap = new UidMap();
70 mConfigManager = new ConfigManager();
71 mProcessor = new StatsLogProcessor(mUidMap);
72
73 mConfigManager->AddListener(mProcessor);
74
75 init_system_properties();
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070076}
77
Yao Chenef99c4f2017-09-22 16:26:54 -070078StatsService::~StatsService() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070079}
80
Joe Onorato9fc9edf2017-10-15 20:08:52 -070081void StatsService::init_system_properties() {
82 mEngBuild = false;
83 const prop_info* buildType = __system_property_find("ro.build.type");
84 if (buildType != NULL) {
85 __system_property_read_callback(buildType, init_build_type_callback, this);
86 }
David Chen0656b7a2017-09-13 15:53:39 -070087}
88
Joe Onorato9fc9edf2017-10-15 20:08:52 -070089void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
90 uint32_t serial) {
Yao Chen729093d2017-10-16 10:33:26 -070091 if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -070092 reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
93 }
94}
95
96/**
97 * Implement our own because the default binder implementation isn't
98 * properly handling SHELL_COMMAND_TRANSACTION.
99 */
Yao Chenef99c4f2017-09-22 16:26:54 -0700100status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
101 uint32_t flags) {
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700102 status_t err;
103
104 switch (code) {
105 case SHELL_COMMAND_TRANSACTION: {
106 int in = data.readFileDescriptor();
107 int out = data.readFileDescriptor();
108 int err = data.readFileDescriptor();
109 int argc = data.readInt32();
110 Vector<String8> args;
111 for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
112 args.add(String8(data.readString16()));
113 }
Yao Chenef99c4f2017-09-22 16:26:54 -0700114 sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder());
115 sp<IResultReceiver> resultReceiver =
116 IResultReceiver::asInterface(data.readStrongBinder());
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700117
118 FILE* fin = fdopen(in, "r");
119 FILE* fout = fdopen(out, "w");
120 FILE* ferr = fdopen(err, "w");
121
122 if (fin == NULL || fout == NULL || ferr == NULL) {
123 resultReceiver->send(NO_MEMORY);
124 } else {
125 err = command(fin, fout, ferr, args);
126 resultReceiver->send(err);
127 }
128
129 if (fin != NULL) {
130 fflush(fin);
131 fclose(fin);
132 }
133 if (fout != NULL) {
134 fflush(fout);
135 fclose(fout);
136 }
137 if (fout != NULL) {
138 fflush(ferr);
139 fclose(ferr);
140 }
141
142 return NO_ERROR;
143 }
Yao Chenef99c4f2017-09-22 16:26:54 -0700144 default: { return BnStatsManager::onTransact(code, data, reply, flags); }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700145 }
146}
147
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700148/**
149 * Write debugging data about statsd.
150 */
Yao Chenef99c4f2017-09-22 16:26:54 -0700151status_t StatsService::dump(int fd, const Vector<String16>& args) {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700152 FILE* out = fdopen(fd, "w");
153 if (out == NULL) {
154 return NO_MEMORY; // the fd is already open
155 }
156
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700157 // TODO: Proto format for incident reports
158 dump_impl(out);
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700159
160 fclose(out);
161 return NO_ERROR;
162}
163
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700164/**
165 * Write debugging data about statsd in text format.
166 */
167void StatsService::dump_impl(FILE* out) {
168 mConfigManager->Dump(out);
169}
170
171/**
172 * Implementation of the adb shell cmd stats command.
173 */
Yao Chenef99c4f2017-09-22 16:26:54 -0700174status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700175 // TODO: Permission check
176
177 const int argCount = args.size();
178 if (argCount >= 1) {
179 // adb shell cmd stats config ...
David Chen0656b7a2017-09-13 15:53:39 -0700180 if (!args[0].compare(String8("config"))) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700181 return cmd_config(in, out, err, args);
David Chen0656b7a2017-09-13 15:53:39 -0700182 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700183
184 // adb shell cmd stats print-stats-log
185 if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
186 return cmd_print_stats_log(out, args);
187 }
188
David Chende701692017-10-05 13:16:02 -0700189 if (!args[0].compare(String8("print-uid-map"))) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700190 return cmd_print_uid_map(out);
David Chende701692017-10-05 13:16:02 -0700191 }
Yao Chen729093d2017-10-16 10:33:26 -0700192
193 if (!args[0].compare(String8("dump-report"))) {
194 return cmd_dump_report(out, err, args);
195 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700196 }
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700197
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700198 print_cmd_help(out);
Joe Onorato2cbc2cc2017-08-30 17:03:23 -0700199 return NO_ERROR;
200}
201
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700202void StatsService::print_cmd_help(FILE* out) {
203 fprintf(out,
204 "usage: adb shell cmd stats print-stats-log [tag_required] "
205 "[timestamp_nsec_optional]\n");
206 fprintf(out, "\n");
207 fprintf(out, "\n");
208 fprintf(out, "usage: adb shell cmd stats print-uid-map \n");
209 fprintf(out, "\n");
210 fprintf(out, " Prints the UID, app name, version mapping.\n");
211 fprintf(out, "\n");
212 fprintf(out, "\n");
213 fprintf(out, "usage: adb shell cmd stats config remove [UID] NAME\n");
214 fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
215 fprintf(out, "\n");
216 fprintf(out, " Adds, updates or removes a configuration. The proto should be in\n");
217 fprintf(out, " wire-encoded protobuf format and passed via stdin.\n");
218 fprintf(out, "\n");
219 fprintf(out, " UID The uid to use. It is only possible to pass the UID\n");
220 fprintf(out, " parameter on eng builds. If UID is omitted the calling\n");
221 fprintf(out, " uid is used.\n");
222 fprintf(out, " NAME The per-uid name to use\n");
223}
224
225status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
226 const int argCount = args.size();
227 if (argCount >= 2) {
228 if (args[1] == "update" || args[1] == "remove") {
229 bool good = false;
230 int uid = -1;
231 string name;
232
233 if (argCount == 3) {
234 // Automatically pick the UID
235 uid = IPCThreadState::self()->getCallingUid();
236 // TODO: What if this isn't a binder call? Should we fail?
237 name.assign(args[2].c_str(), args[2].size());
238 good = true;
239 } else if (argCount == 4) {
240 // If it's a userdebug or eng build, then the shell user can
241 // impersonate other uids.
242 if (mEngBuild) {
243 const char* s = args[2].c_str();
244 if (*s != '\0') {
245 char* end = NULL;
246 uid = strtol(s, &end, 0);
247 if (*end == '\0') {
248 name.assign(args[3].c_str(), args[3].size());
249 good = true;
250 }
251 }
252 } else {
Yao Chen729093d2017-10-16 10:33:26 -0700253 fprintf(err,
254 "The config can only be set for other UIDs on eng or userdebug "
255 "builds.\n");
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700256 }
257 }
258
259 if (!good) {
260 // If arg parsing failed, print the help text and return an error.
261 print_cmd_help(out);
262 return UNKNOWN_ERROR;
263 }
264
265 if (args[1] == "update") {
266 // Read stream into buffer.
267 string buffer;
268 if (!android::base::ReadFdToString(fileno(in), &buffer)) {
269 fprintf(err, "Error reading stream for StatsConfig.\n");
270 return UNKNOWN_ERROR;
271 }
272
273 // Parse buffer.
274 StatsdConfig config;
275 if (!config.ParseFromString(buffer)) {
276 fprintf(err, "Error parsing proto stream for StatsConfig.\n");
277 return UNKNOWN_ERROR;
278 }
279
280 // Add / update the config.
281 mConfigManager->UpdateConfig(ConfigKey(uid, name), config);
282 } else {
283 // Remove the config.
284 mConfigManager->RemoveConfig(ConfigKey(uid, name));
285 }
286
287 return NO_ERROR;
288 }
David Chen0656b7a2017-09-13 15:53:39 -0700289 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700290 print_cmd_help(out);
291 return UNKNOWN_ERROR;
292}
293
Yao Chen729093d2017-10-16 10:33:26 -0700294status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args) {
295 if (mProcessor != nullptr) {
296 const int argCount = args.size();
297 bool good = false;
298 int uid;
299 string name;
300 if (argCount == 2) {
301 // Automatically pick the UID
302 uid = IPCThreadState::self()->getCallingUid();
303 // TODO: What if this isn't a binder call? Should we fail?
304 name.assign(args[2].c_str(), args[2].size());
305 good = true;
306 } else if (argCount == 3) {
307 // If it's a userdebug or eng build, then the shell user can
308 // impersonate other uids.
309 if (mEngBuild) {
310 const char* s = args[1].c_str();
311 if (*s != '\0') {
312 char* end = NULL;
313 uid = strtol(s, &end, 0);
314 if (*end == '\0') {
315 name.assign(args[2].c_str(), args[2].size());
316 good = true;
317 }
318 }
319 } else {
320 fprintf(out,
321 "The metrics can only be dumped for other UIDs on eng or userdebug "
322 "builds.\n");
323 }
324 }
325 if (good) {
326 mProcessor->onDumpReport(ConfigKey(uid, name));
327 // TODO: print the returned StatsLogReport to file instead of printing to logcat.
328 fprintf(out, "Dump report for Config [%d,%s]\n", uid, name.c_str());
329 fprintf(out, "See the StatsLogReport in logcat...\n");
330 return android::OK;
331 } else {
332 // If arg parsing failed, print the help text and return an error.
333 print_cmd_help(out);
334 return UNKNOWN_ERROR;
335 }
336 } else {
337 fprintf(out, "Log processor does not exist...\n");
338 return UNKNOWN_ERROR;
339 }
340}
341
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700342status_t StatsService::cmd_print_stats_log(FILE* out, const Vector<String8>& args) {
343 long msec = 0;
344
345 if (args.size() > 2) {
346 msec = strtol(args[2].string(), NULL, 10);
David Chen0656b7a2017-09-13 15:53:39 -0700347 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700348 return DropboxReader::readStatsLogs(out, args[1].string(), msec);
349}
350
351status_t StatsService::cmd_print_uid_map(FILE* out) {
352 mUidMap->printUidMap(out);
353 return NO_ERROR;
David Chen0656b7a2017-09-13 15:53:39 -0700354}
355
David Chende701692017-10-05 13:16:02 -0700356Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
357 const vector<String16>& app) {
358 if (DEBUG) ALOGD("StatsService::informAllUidData was called");
359
360 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
361 return Status::fromExceptionCode(Status::EX_SECURITY,
362 "Only system uid can call informAllUidData");
363 }
364
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700365 mUidMap->updateMap(uid, version, app);
David Chende701692017-10-05 13:16:02 -0700366 if (DEBUG) ALOGD("StatsService::informAllUidData succeeded");
367
368 return Status::ok();
369}
370
371Status StatsService::informOnePackage(const String16& app, int32_t uid, int32_t version) {
372 if (DEBUG) ALOGD("StatsService::informOnePackage was called");
373
374 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
375 return Status::fromExceptionCode(Status::EX_SECURITY,
376 "Only system uid can call informOnePackage");
377 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700378 mUidMap->updateApp(app, uid, version);
David Chende701692017-10-05 13:16:02 -0700379 return Status::ok();
380}
381
382Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
383 if (DEBUG) ALOGD("StatsService::informOnePackageRemoved was called");
384
385 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
386 return Status::fromExceptionCode(Status::EX_SECURITY,
387 "Only system uid can call informOnePackageRemoved");
388 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700389 mUidMap->removeApp(app, uid);
David Chende701692017-10-05 13:16:02 -0700390 return Status::ok();
391}
392
Yao Chenef99c4f2017-09-22 16:26:54 -0700393Status StatsService::informAnomalyAlarmFired() {
Bookatzb487b552017-09-18 11:26:01 -0700394 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700395
396 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
397 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700398 "Only system uid can call informAnomalyAlarmFired");
Bookatz1b0b1142017-09-08 11:58:42 -0700399 }
400
Bookatzb487b552017-09-18 11:26:01 -0700401 if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700402 // TODO: check through all counters/timers and see if an anomaly has indeed occurred.
403
404 return Status::ok();
405}
406
Yao Chenef99c4f2017-09-22 16:26:54 -0700407Status StatsService::informPollAlarmFired() {
Bookatzb487b552017-09-18 11:26:01 -0700408 if (DEBUG) ALOGD("StatsService::informPollAlarmFired was called");
Bookatz1b0b1142017-09-08 11:58:42 -0700409
410 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
411 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700412 "Only system uid can call informPollAlarmFired");
Bookatz1b0b1142017-09-08 11:58:42 -0700413 }
414
Bookatzb487b552017-09-18 11:26:01 -0700415 if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
Bookatz1b0b1142017-09-08 11:58:42 -0700416 // TODO: determine what services to poll and poll (or ask StatsCompanionService to poll) them.
Chenjie Yu1a317ba2017-10-05 16:05:32 -0700417 String16 output = mStatsPullerManager.pull(StatsPullerManager::KERNEL_WAKELOCKS);
Bookatzc68a9d22017-09-27 14:09:55 -0700418 // TODO: do something useful with the output instead of writing a string to screen.
419 ALOGD("%s", String8(output).string());
Chenjie Yu1a317ba2017-10-05 16:05:32 -0700420 ALOGD("%d", int(output.size()));
Bookatz1b0b1142017-09-08 11:58:42 -0700421
422 return Status::ok();
423}
424
Yao Chenef99c4f2017-09-22 16:26:54 -0700425Status StatsService::systemRunning() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700426 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
427 return Status::fromExceptionCode(Status::EX_SECURITY,
Yao Chenef99c4f2017-09-22 16:26:54 -0700428 "Only system uid can call systemRunning");
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700429 }
430
431 // When system_server is up and running, schedule the dropbox task to run.
432 ALOGD("StatsService::systemRunning");
433
Bookatzb487b552017-09-18 11:26:01 -0700434 sayHiToStatsCompanion();
435
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700436 return Status::ok();
437}
438
Yao Chenef99c4f2017-09-22 16:26:54 -0700439void StatsService::sayHiToStatsCompanion() {
440 // TODO: This method needs to be private. It is temporarily public and unsecured for testing
441 // purposes.
Bookatzb487b552017-09-18 11:26:01 -0700442 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
443 if (statsCompanion != nullptr) {
444 if (DEBUG) ALOGD("Telling statsCompanion that statsd is ready");
445 statsCompanion->statsdReady();
446 } else {
447 if (DEBUG) ALOGD("Could not access statsCompanion");
448 }
449}
450
Yao Chenef99c4f2017-09-22 16:26:54 -0700451sp<IStatsCompanionService> StatsService::getStatsCompanionService() {
Bookatz906a35c2017-09-20 15:26:44 -0700452 sp<IStatsCompanionService> statsCompanion = nullptr;
453 // Get statscompanion service from service manager
454 const sp<IServiceManager> sm(defaultServiceManager());
455 if (sm != nullptr) {
456 const String16 name("statscompanion");
457 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
458 if (statsCompanion == nullptr) {
459 ALOGW("statscompanion service unavailable!");
460 return nullptr;
461 }
462 }
463 return statsCompanion;
464}
465
Yao Chenef99c4f2017-09-22 16:26:54 -0700466Status StatsService::statsCompanionReady() {
Bookatzb487b552017-09-18 11:26:01 -0700467 if (DEBUG) ALOGD("StatsService::statsCompanionReady was called");
468
469 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
470 return Status::fromExceptionCode(Status::EX_SECURITY,
471 "Only system uid can call statsCompanionReady");
472 }
473
474 sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
475 if (statsCompanion == nullptr) {
Yao Chenef99c4f2017-09-22 16:26:54 -0700476 return Status::fromExceptionCode(
477 Status::EX_NULL_POINTER,
478 "statscompanion unavailable despite it contacting statsd!");
Bookatzb487b552017-09-18 11:26:01 -0700479 }
480 if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion.");
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700481 IInterface::asBinder(statsCompanion)->linkToDeath(new CompanionDeathRecipient(mAnomalyMonitor));
Bookatzb487b552017-09-18 11:26:01 -0700482 mAnomalyMonitor->setStatsCompanionService(statsCompanion);
483
484 return Status::ok();
485}
486
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700487void StatsService::Startup() {
488 mConfigManager->Startup();
Bookatz906a35c2017-09-20 15:26:44 -0700489}
490
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700491void StatsService::OnLogEvent(const LogEvent& event) {
492 mProcessor->OnLogEvent(event);
Bookatz906a35c2017-09-20 15:26:44 -0700493}
494
Yao Chenef99c4f2017-09-22 16:26:54 -0700495} // namespace statsd
496} // namespace os
497} // namespace android