Clean up how we handle configurations, and other assorted cleanup

- Add a ConfigManager class that tracks the configurations
  that have been passed to us.  Configurations are now
  tracked by tuples of (uid,tag), where the tag is an
  app-defined string, in case a single uid has multiple
  configurations.
- Move all of the initialization into StatsService.
- Get rid of the ability to have multiple LogListeners. Raw
  events are now pushed directly into StatsService, which
  can distribute them to the interested parties (and will
  eventually be able to do the proper locking).
- Add Log.h, which sets our LOG_TAG correctly.
- Move some of the related files that I expect will grow some
  into their own subdirectories.

Test: statsd_test
Test: adb shell cmd stats config ...
Test: adb shell dumpsys stats
Change-Id: I79487603003d8a842d5bd319741f1ecbf72063d1
This commit is contained in:
Joe Onorato
2017-10-15 20:08:52 -07:00
parent aeff5b880b
commit 9fc9edf95a
55 changed files with 1317 additions and 645 deletions

View File

@@ -14,16 +14,23 @@
LOCAL_PATH:= $(call my-dir)
statsd_common_src := \
../../core/java/android/os/IStatsCompanionService.aidl \
../../core/java/android/os/IStatsManager.aidl \
src/stats_log.proto \
src/statsd_config.proto \
src/stats_events_copy.proto \
src/anomaly/AnomalyMonitor.cpp \
src/condition/CombinationConditionTracker.cpp \
src/condition/condition_util.cpp \
src/condition/SimpleConditionTracker.cpp \
src/config/ConfigKey.cpp \
src/config/ConfigListener.cpp \
src/config/ConfigManager.cpp \
src/external/KernelWakelockPuller.cpp \
src/external/StatsPullerManager.cpp \
src/logd/LogListener.cpp \
src/logd/LogReader.cpp \
src/matchers/CombinationLogMatchingTracker.cpp \
src/matchers/matcher_util.cpp \
src/matchers/SimpleLogMatchingTracker.cpp \
@@ -31,17 +38,12 @@ statsd_common_src := \
src/metrics/CountMetricProducer.cpp \
src/metrics/MetricsManager.cpp \
src/metrics/metrics_manager_util.cpp \
src/AnomalyMonitor.cpp \
src/DropboxReader.cpp \
src/DropboxWriter.cpp \
src/KernelWakelockPuller.cpp \
src/LogEntryPrinter.cpp \
src/LogReader.cpp \
src/packages/UidMap.cpp \
src/storage/DropboxReader.cpp \
src/storage/DropboxWriter.cpp \
src/StatsLogProcessor.cpp \
src/StatsPullerManager.cpp \
src/StatsService.cpp \
src/stats_util.cpp \
src/UidMap.cpp
src/stats_util.cpp
statsd_common_c_includes := \
$(LOCAL_PATH)/src
@@ -125,13 +127,15 @@ LOCAL_CFLAGS += \
LOCAL_SRC_FILES := \
$(statsd_common_src) \
tests/AnomalyMonitor_test.cpp \
tests/ConditionTracker_test.cpp \
tests/ConfigManager_test.cpp \
tests/indexed_priority_queue_test.cpp \
tests/LogEntryMatcher_test.cpp \
tests/LogReader_test.cpp \
tests/MetricsManager_test.cpp \
tests/UidMap_test.cpp \
tests/LogEntryMatcher_test.cpp \
tests/AnomalyMonitor_test.cpp \
tests/ConditionTracker_test.cpp
tests/UidMap_test.cpp
LOCAL_STATIC_LIBRARIES := \
libgmock

30
cmds/statsd/src/Log.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file must be included at the top of the file. Other header files
* occasionally include log.h, and if LOG_TAG isn't set when that happens
* we'll get a preprocesser error when we try to define it here.
*/
#pragma once
#define LOG_TAG "statsd"
#include <log/log.h>
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <LogEntryPrinter.h>
#include <log/event_tag_map.h>
#include <log/logprint.h>
#include <utils/Errors.h>
#include "matchers/matcher_util.h"
#define PRINT_WITH_LIBLOG 0
#define PRINT_WITH_LOG_EVENT_WRAPPER 1
using namespace android;
namespace android {
namespace os {
namespace statsd {
LogEntryPrinter::LogEntryPrinter(int out) : m_out(out) {
// Initialize the EventTagMap, which is how we know the names of the numeric event tags.
// If this fails, we can't print well, but something will print.
m_tags = android_openEventTagMap(NULL);
// Printing format
m_format = android_log_format_new();
android_log_setPrintFormat(m_format, FORMAT_THREADTIME);
}
LogEntryPrinter::~LogEntryPrinter() {
if (m_tags != NULL) {
android_closeEventTagMap(m_tags);
}
android_log_format_free(m_format);
}
void LogEntryPrinter::OnLogEvent(const log_msg& msg) {
if (PRINT_WITH_LIBLOG) {
status_t err;
AndroidLogEntry entry;
char buf[1024];
err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry,
m_tags, buf, sizeof(buf));
if (err == NO_ERROR) {
android_log_printLogLine(m_format, m_out, &entry);
} else {
printf("log entry: %s\n", buf);
fflush(stdout);
}
}
if (PRINT_WITH_LOG_EVENT_WRAPPER) {
LogEventWrapper event = parseLogEvent(msg);
printf("event: %s\n", event.toString().c_str());
fflush(stdout);
}
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -14,12 +14,14 @@
* limitations under the License.
*/
#include <StatsLogProcessor.h>
#include "Log.h"
#include "StatsLogProcessor.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "metrics/CountMetricProducer.h"
#include "stats_util.h"
#include <cutils/log.h>
#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
#include <log/log_event_list.h>
#include <metrics/CountMetricProducer.h>
#include <utils/Errors.h>
using namespace android;
@@ -31,12 +33,8 @@ namespace android {
namespace os {
namespace statsd {
StatsLogProcessor::StatsLogProcessor(const sp<UidMap> &uidMap)
: m_dropbox_writer("all-logs"), m_UidMap(uidMap)
{
// hardcoded config
// this should be called from StatsService when it receives a statsd_config
UpdateConfig(0, buildFakeConfig());
StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap)
: m_dropbox_writer("all-logs"), mUidMap(uidMap) {
}
StatsLogProcessor::~StatsLogProcessor() {
@@ -54,17 +52,18 @@ void StatsLogProcessor::OnLogEvent(const log_msg& msg) {
}
}
void StatsLogProcessor::UpdateConfig(const int config_source, const StatsdConfig& config) {
auto it = mMetricsManagers.find(config_source);
void StatsLogProcessor::OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) {
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
it->second->finish();
}
ALOGD("Updated configuration for source %i", config_source);
ALOGD("Updated configuration for key %s", key.ToString().c_str());
unique_ptr<MetricsManager> newMetricsManager = std::make_unique<MetricsManager>(config);
if (newMetricsManager->isConfigValid()) {
mMetricsManagers.insert({config_source, std::move(newMetricsManager)});
mMetricsManagers[key] = std::move(newMetricsManager);
// Why doesn't this work? mMetricsManagers.insert({key, std::move(newMetricsManager)});
ALOGD("StatsdConfig valid");
} else {
// If there is any error in the config, don't use it.
@@ -72,6 +71,14 @@ void StatsLogProcessor::UpdateConfig(const int config_source, const StatsdConfig
}
}
void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
it->second->finish();
mMetricsManagers.erase(it);
}
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -16,12 +16,13 @@
#ifndef STATS_LOG_PROCESSOR_H
#define STATS_LOG_PROCESSOR_H
#include "DropboxWriter.h"
#include "LogReader.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "config/ConfigListener.h"
#include "logd/LogReader.h"
#include "metrics/MetricsManager.h"
#include "stats_util.h"
#include "UidMap.h"
#include "packages/UidMap.h"
#include "storage/DropboxWriter.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include <log/logprint.h>
#include <stdio.h>
@@ -31,22 +32,23 @@ namespace android {
namespace os {
namespace statsd {
class StatsLogProcessor : public LogListener {
class StatsLogProcessor : public ConfigListener {
public:
StatsLogProcessor(const sp<UidMap> &uidMap);
virtual ~StatsLogProcessor();
virtual void OnLogEvent(const log_msg& msg);
void UpdateConfig(const int config_source, const StatsdConfig& config);
void OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config);
void OnConfigRemoved(const ConfigKey& key);
private:
// TODO: use EventMetrics to log the events.
DropboxWriter m_dropbox_writer;
std::unordered_map<int, std::unique_ptr<MetricsManager>> mMetricsManagers;
std::unordered_map<ConfigKey, std::unique_ptr<MetricsManager>> mMetricsManagers;
sp<UidMap> m_UidMap; // Reference to the UidMap to lookup app name and version for each uid.
sp<UidMap> mUidMap; // Reference to the UidMap to lookup app name and version for each uid.
};
} // namespace statsd

View File

@@ -14,16 +14,15 @@
* limitations under the License.
*/
#define LOG_TAG "statsd"
#define DEBUG true
#include "Log.h"
#include "StatsService.h"
#include "DropboxReader.h"
#include "storage/DropboxReader.h"
#include <android-base/file.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <cutils/log.h>
#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
#include <private/android_filesystem_config.h>
#include <utils/Looper.h>
@@ -31,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/system_properties.h>
#include <unistd.h>
using namespace android;
@@ -39,24 +39,65 @@ namespace android {
namespace os {
namespace statsd {
// ======================================================================
/**
* Watches for the death of the stats companion (system process).
*/
class CompanionDeathRecipient : public IBinder::DeathRecipient {
public:
CompanionDeathRecipient(const sp<AnomalyMonitor>& anomalyMonitor);
virtual void binderDied(const wp<IBinder>& who);
private:
const sp<AnomalyMonitor> mAnomalyMonitor;
};
CompanionDeathRecipient::CompanionDeathRecipient(const sp<AnomalyMonitor>& anomalyMonitor)
: mAnomalyMonitor(anomalyMonitor) {
}
void CompanionDeathRecipient::binderDied(const wp<IBinder>& who) {
ALOGW("statscompanion service died");
mAnomalyMonitor->setStatsCompanionService(nullptr);
}
// ======================================================================
StatsService::StatsService(const sp<Looper>& handlerLooper)
: mAnomalyMonitor(new AnomalyMonitor(2)),m_UidMap(new UidMap()), mStatsPullerManager()
// TODO: Change AnomalyMonitor initialization based on the config
: mStatsPullerManager(),
mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Put this comment somewhere better
{
ALOGD("stats service constructed");
mUidMap = new UidMap();
mConfigManager = new ConfigManager();
mProcessor = new StatsLogProcessor(mUidMap);
mConfigManager->AddListener(mProcessor);
init_system_properties();
}
StatsService::~StatsService() {
}
status_t StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) {
m_processor = main_processor;
ALOGD("stats service set to processor %p", m_processor.get());
return NO_ERROR;
void StatsService::init_system_properties() {
mEngBuild = false;
const prop_info* buildType = __system_property_find("ro.build.type");
if (buildType != NULL) {
__system_property_read_callback(buildType, init_build_type_callback, this);
}
}
// Implement our own because the default binder implementation isn't
// properly handling SHELL_COMMAND_TRANSACTION
void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
uint32_t serial) {
if (0 == strcmp("eng", value)) {
reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
}
}
/**
* Implement our own because the default binder implementation isn't
* properly handling SHELL_COMMAND_TRANSACTION.
*/
status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
status_t err;
@@ -105,56 +146,159 @@ status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* rep
}
}
/**
* Write debugging data about statsd.
*/
status_t StatsService::dump(int fd, const Vector<String16>& args) {
FILE* out = fdopen(fd, "w");
if (out == NULL) {
return NO_MEMORY; // the fd is already open
}
fprintf(out, "StatsService::dump:");
ALOGD("StatsService::dump:");
const int N = args.size();
for (int i = 0; i < N; i++) {
fprintf(out, " %s", String8(args[i]).string());
ALOGD(" %s", String8(args[i]).string());
}
fprintf(out, "\n");
// TODO: Proto format for incident reports
dump_impl(out);
fclose(out);
return NO_ERROR;
}
/**
* Write debugging data about statsd in text format.
*/
void StatsService::dump_impl(FILE* out) {
mConfigManager->Dump(out);
}
/**
* Implementation of the adb shell cmd stats command.
*/
status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
if (args.size() > 0) {
if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
return doPrintStatsLog(out, args);
}
// TODO: Permission check
const int argCount = args.size();
if (argCount >= 1) {
// adb shell cmd stats config ...
if (!args[0].compare(String8("config"))) {
return doLoadConfig(in);
return cmd_config(in, out, err, args);
}
// adb shell cmd stats print-stats-log
if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) {
return cmd_print_stats_log(out, args);
}
// adb shell cmd stats print-stats-log
if (!args[0].compare(String8("print-uid-map"))) {
return doPrintUidMap(out);
return cmd_print_uid_map(out);
}
}
printCmdHelp(out);
print_cmd_help(out);
return NO_ERROR;
}
status_t StatsService::doLoadConfig(FILE* in) {
string content;
if (!android::base::ReadFdToString(fileno(in), &content)) {
return UNKNOWN_ERROR;
void StatsService::print_cmd_help(FILE* out) {
fprintf(out,
"usage: adb shell cmd stats print-stats-log [tag_required] "
"[timestamp_nsec_optional]\n");
fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "usage: adb shell cmd stats print-uid-map \n");
fprintf(out, "\n");
fprintf(out, " Prints the UID, app name, version mapping.\n");
fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "usage: adb shell cmd stats config remove [UID] NAME\n");
fprintf(out, "usage: adb shell cmd stats config update [UID] NAME\n");
fprintf(out, "\n");
fprintf(out, " Adds, updates or removes a configuration. The proto should be in\n");
fprintf(out, " wire-encoded protobuf format and passed via stdin.\n");
fprintf(out, "\n");
fprintf(out, " UID The uid to use. It is only possible to pass the UID\n");
fprintf(out, " parameter on eng builds. If UID is omitted the calling\n");
fprintf(out, " uid is used.\n");
fprintf(out, " NAME The per-uid name to use\n");
}
status_t StatsService::cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
const int argCount = args.size();
if (argCount >= 2) {
if (args[1] == "update" || args[1] == "remove") {
bool good = false;
int uid = -1;
string name;
if (argCount == 3) {
// Automatically pick the UID
uid = IPCThreadState::self()->getCallingUid();
// TODO: What if this isn't a binder call? Should we fail?
name.assign(args[2].c_str(), args[2].size());
good = true;
} else if (argCount == 4) {
// If it's a userdebug or eng build, then the shell user can
// impersonate other uids.
if (mEngBuild) {
const char* s = args[2].c_str();
if (*s != '\0') {
char* end = NULL;
uid = strtol(s, &end, 0);
if (*end == '\0') {
name.assign(args[3].c_str(), args[3].size());
good = true;
}
}
} else {
fprintf(err, "The config can only be set for other UIDs on eng builds.\n");
}
}
if (!good) {
// If arg parsing failed, print the help text and return an error.
print_cmd_help(out);
return UNKNOWN_ERROR;
}
if (args[1] == "update") {
// Read stream into buffer.
string buffer;
if (!android::base::ReadFdToString(fileno(in), &buffer)) {
fprintf(err, "Error reading stream for StatsConfig.\n");
return UNKNOWN_ERROR;
}
// Parse buffer.
StatsdConfig config;
if (!config.ParseFromString(buffer)) {
fprintf(err, "Error parsing proto stream for StatsConfig.\n");
return UNKNOWN_ERROR;
}
// Add / update the config.
mConfigManager->UpdateConfig(ConfigKey(uid, name), config);
} else {
// Remove the config.
mConfigManager->RemoveConfig(ConfigKey(uid, name));
}
return NO_ERROR;
}
}
StatsdConfig config;
if (config.ParseFromString(content)) {
ALOGD("Config parsed from command line: %s", config.SerializeAsString().c_str());
m_processor->UpdateConfig(0, config);
return NO_ERROR;
} else {
ALOGD("Config failed to be parsed");
return UNKNOWN_ERROR;
print_cmd_help(out);
return UNKNOWN_ERROR;
}
status_t StatsService::cmd_print_stats_log(FILE* out, const Vector<String8>& args) {
long msec = 0;
if (args.size() > 2) {
msec = strtol(args[2].string(), NULL, 10);
}
return DropboxReader::readStatsLogs(out, args[1].string(), msec);
}
status_t StatsService::cmd_print_uid_map(FILE* out) {
mUidMap->printUidMap(out);
return NO_ERROR;
}
Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
@@ -166,7 +310,7 @@ Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<i
"Only system uid can call informAllUidData");
}
m_UidMap->updateMap(uid, version, app);
mUidMap->updateMap(uid, version, app);
if (DEBUG) ALOGD("StatsService::informAllUidData succeeded");
return Status::ok();
@@ -179,7 +323,7 @@ Status StatsService::informOnePackage(const String16& app, int32_t uid, int32_t
return Status::fromExceptionCode(Status::EX_SECURITY,
"Only system uid can call informOnePackage");
}
m_UidMap->updateApp(app, uid, version);
mUidMap->updateApp(app, uid, version);
return Status::ok();
}
@@ -190,7 +334,7 @@ Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
return Status::fromExceptionCode(Status::EX_SECURITY,
"Only system uid can call informOnePackageRemoved");
}
m_UidMap->removeApp(app, uid);
mUidMap->removeApp(app, uid);
return Status::ok();
}
@@ -282,38 +426,18 @@ Status StatsService::statsCompanionReady() {
"statscompanion unavailable despite it contacting statsd!");
}
if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion.");
IInterface::asBinder(statsCompanion)->linkToDeath(new StatsdDeathRecipient(mAnomalyMonitor));
IInterface::asBinder(statsCompanion)->linkToDeath(new CompanionDeathRecipient(mAnomalyMonitor));
mAnomalyMonitor->setStatsCompanionService(statsCompanion);
return Status::ok();
}
void StatsdDeathRecipient::binderDied(const wp<IBinder>& who) {
ALOGW("statscompanion service died");
mAnmlyMntr->setStatsCompanionService(nullptr);
void StatsService::Startup() {
mConfigManager->Startup();
}
status_t StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) {
long msec = 0;
if (args.size() > 2) {
msec = strtol(args[2].string(), NULL, 10);
}
return DropboxReader::readStatsLogs(out, args[1].string(), msec);
}
status_t StatsService::doPrintUidMap(FILE* out) {
m_UidMap->printUidMap(out);
return NO_ERROR;
}
void StatsService::printCmdHelp(FILE* out) {
fprintf(out, "Usage:\n");
fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n");
fprintf(out, "\t print-uid-map Prints the UID, app name, version mapping.\n");
fprintf(out,
"\t config\t Loads a new config from command-line (must be proto in wire-encoded "
"format).\n");
void StatsService::OnLogEvent(const log_msg& msg) {
mProcessor->OnLogEvent(msg);
}
} // namespace statsd

View File

@@ -17,11 +17,11 @@
#ifndef STATS_SERVICE_H
#define STATS_SERVICE_H
#include "AnomalyMonitor.h"
#include "StatsLogProcessor.h"
#include "StatsPullerManager.h"
#include "StatsPuller.h"
#include "UidMap.h"
#include "anomaly/AnomalyMonitor.h"
#include "config/ConfigManager.h"
#include "external/StatsPullerManager.h"
#include "packages/UidMap.h"
#include <android/os/BnStatsManager.h>
#include <android/os/IStatsCompanionService.h>
@@ -42,75 +42,114 @@ namespace android {
namespace os {
namespace statsd {
class StatsService : public BnStatsManager {
class StatsService : public BnStatsManager, public LogListener {
public:
StatsService(const sp<Looper>& handlerLooper);
virtual ~StatsService();
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
virtual Status systemRunning();
// Inform statsd that statsCompanion is ready.
virtual Status statsCompanionReady();
virtual Status informAnomalyAlarmFired();
virtual Status informPollAlarmFired();
virtual Status informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
const vector<String16>& app);
virtual Status informOnePackage(const String16& app, int32_t uid, int32_t version);
virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
virtual status_t setProcessor(const sp<StatsLogProcessor>& main_processor);
/**
* Called right before we start processing events.
*/
void Startup();
/**
* Called by LogReader when there's a log event to process.
*/
virtual void OnLogEvent(const log_msg& msg);
// TODO: public for testing since statsd doesn't run when system starts. Change to private
// later.
/** Inform statsCompanion that statsd is ready. */
virtual void sayHiToStatsCompanion();
// TODO: Move this to a more logical file/class
// TODO: Should be private. Temporarily public for testing purposes only.
const sp<AnomalyMonitor> mAnomalyMonitor;
sp<UidMap> getUidMap() {
return m_UidMap;
}
/** Fetches and returns the StatsCompanionService. */
static sp<IStatsCompanionService> getStatsCompanionService();
private:
sp<UidMap> m_UidMap; // Reference to the UID map needed for translating UID to app name/version.
/**
* Load system properties at init.
*/
void init_system_properties();
sp<StatsLogProcessor> m_processor; // Reference to the processor for updating configs.
/**
* Helper for loading system properties.
*/
static void init_build_type_callback(void* cookie, const char* name, const char* value,
uint32_t serial);
status_t doPrintStatsLog(FILE* out, const Vector<String8>& args);
/**
* Text output of dumpsys.
*/
void dump_impl(FILE* out);
void printCmdHelp(FILE* out);
/**
* Print usage information for the commands
*/
void print_cmd_help(FILE* out);
status_t doLoadConfig(FILE* in);
/**
* Handle the config sub-command.
*/
status_t cmd_config(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
/**
* Print the event log.
*/
status_t cmd_print_stats_log(FILE* out, const Vector<String8>& args);
/**
* Print the mapping of uids to package names.
*/
status_t cmd_print_uid_map(FILE* out);
/**
* Update a configuration.
*/
void set_config(int uid, const string& name, const StatsdConfig& config);
/**
* Tracks the uid <--> package name mapping.
*/
sp<UidMap> mUidMap;
/**
* Fetches external metrics.
* TODO: This should be an sp<>
*/
StatsPullerManager mStatsPullerManager;
status_t doPrintUidMap(FILE* out);
};
/**
* Tracks the configurations that have been passed to statsd.
*/
sp<ConfigManager> mConfigManager;
// --- StatsdDeathRecipient ---
class StatsdDeathRecipient : public IBinder::DeathRecipient {
public:
StatsdDeathRecipient(sp<AnomalyMonitor> anomalyMonitor) : mAnmlyMntr(anomalyMonitor) {
}
/**
* The metrics recorder.
*/
sp<StatsLogProcessor> mProcessor;
virtual void binderDied(const wp<IBinder>& who);
/**
* The anomaly detector.
*/
const sp<AnomalyMonitor> mAnomalyMonitor;
private:
const sp<AnomalyMonitor> mAnmlyMntr;
/**
* Whether this is an eng build.
*/
bool mEngBuild;
};
} // namespace statsd

View File

@@ -14,12 +14,10 @@
* limitations under the License.
*/
#define LOG_TAG "AnomalyMonitor"
#define DEBUG true
#include "Log.h"
#include "AnomalyMonitor.h"
#include <cutils/log.h>
#include "anomaly/AnomalyMonitor.h"
namespace android {
namespace os {
@@ -92,17 +90,16 @@ void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) {
// More efficient than repeatedly calling remove(mPq.top()) since it batches the
// updates to the registered alarm.
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>
AnomalyMonitor::popSoonerThan(uint32_t timestampSec) {
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> AnomalyMonitor::popSoonerThan(
uint32_t timestampSec) {
if (DEBUG) ALOGD("Removing alarms with time <= %u", timestampSec);
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> oldAlarms;
std::lock_guard<std::mutex> lock(mLock);
for (sp<const AnomalyAlarm> t = mPq.top();
t != nullptr && t->timestampSec <= timestampSec; t = mPq.top()) {
for (sp<const AnomalyAlarm> t = mPq.top(); t != nullptr && t->timestampSec <= timestampSec;
t = mPq.top()) {
oldAlarms.insert(t);
mPq.pop(); // remove t
mPq.pop(); // remove t
}
// Always update registered alarm time (if anything has changed).
if (!oldAlarms.empty()) {

View File

@@ -17,12 +17,13 @@
#ifndef ANOMALY_MONITOR_H
#define ANOMALY_MONITOR_H
#include "anomaly/indexed_priority_queue.h"
#include <android/os/IStatsCompanionService.h>
#include <indexed_priority_queue.h>
#include <utils/RefBase.h>
#include <unordered_set>
#include <queue>
#include <unordered_set>
#include <vector>
using namespace android;
@@ -91,8 +92,8 @@ public:
* Returns and removes all alarms whose timestamp <= the given timestampSec.
* Always updates the registered alarm if return is non-empty.
*/
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>
popSoonerThan(uint32_t timestampSec);
unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> popSoonerThan(
uint32_t timestampSec);
/**
* Returns the projected alarm timestamp that is registered with
@@ -144,4 +145,4 @@ private:
} // namespace os
} // namespace android
#endif // ANOMALY_MONITOR_H
#endif // ANOMALY_MONITOR_H

View File

@@ -14,15 +14,10 @@
* limitations under the License.
*/
#ifndef STATSD_INDEXED_PRIORITY_QUEUE_H
#define STATSD_INDEXED_PRIORITY_QUEUE_H
#pragma once
// ALOGE can be called from this file. If header loaded by another class, use their LOG_TAG instead.
#ifndef LOG_TAG
#define LOG_TAG "statsd(indexed_priority_queue)"
#endif // LOG_TAG
#include "Log.h"
#include <cutils/log.h>
#include <utils/RefBase.h>
#include <unordered_map>
#include <vector>
@@ -132,23 +127,23 @@ void indexed_priority_queue<AA, Comparator>::remove(sp<const AA> a) {
// The same as, but slightly more efficient than, remove(top()).
template <class AA, class Comparator>
void indexed_priority_queue<AA, Comparator>::pop() {
sp<const AA> a = top();
if (a == nullptr) return;
const size_t idx = 1;
if (idx == size()) { // if a is the last element
sp<const AA> a = top();
if (a == nullptr) return;
const size_t idx = 1;
if (idx == size()) { // if a is the last element
pq.pop_back();
indices.erase(a);
return;
}
// move last element (guaranteed not to be at idx) to idx, then delete a
sp<const AA> last_a = pq.back();
pq[idx] = last_a;
pq.pop_back();
indices[last_a] = idx;
indices.erase(a);
return;
}
// move last element (guaranteed not to be at idx) to idx, then delete a
sp<const AA> last_a = pq.back();
pq[idx] = last_a;
pq.pop_back();
indices[last_a] = idx;
indices.erase(a);
// get the heap back in order (since the element at idx is not in order)
sift_down(idx);
// get the heap back in order (since the element at idx is not in order)
sift_down(idx);
}
template <class AA, class Comparator>
@@ -227,5 +222,3 @@ void indexed_priority_queue<AA, Comparator>::swap_indices(size_t i, size_t j) {
} // namespace statsd
} // namespace os
} // namespace android
#endif // STATSD_INDEXED_PRIORITY_QUEUE_H

View File

@@ -13,23 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "CombinationConditionTracker"
#define DEBUG true // STOPSHIP if true
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);
#include "Log.h"
#include "CombinationConditionTracker.h"
#include <cutils/log.h>
#include <log/logprint.h>
using std::string;
using std::unique_ptr;
using std::unordered_map;
using std::vector;
namespace android {
namespace os {
namespace statsd {
using std::string;
using std::unique_ptr;
using std::unordered_map;
using std::vector;
CombinationConditionTracker::CombinationConditionTracker(const string& name, const int index)
: ConditionTracker(name, index) {
VLOG("creating CombinationConditionTracker %s", mName.c_str());

View File

@@ -14,17 +14,19 @@
* limitations under the License.
*/
#ifndef CONDITION_TRACKER_H
#define CONDITION_TRACKER_H
#pragma once
#include "Log.h"
#include "condition/condition_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "matchers/LogMatchingTracker.h"
#include "matchers/matcher_util.h"
#include <cutils/log.h>
#include <log/logprint.h>
#include <utils/RefBase.h>
#include <unordered_map>
#include "../matchers/LogMatchingTracker.h"
#include "../matchers/matcher_util.h"
#include "condition_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
namespace android {
namespace os {
@@ -102,4 +104,3 @@ protected:
} // namespace os
} // namespace android
#endif // CONDITION_TRACKER_H

View File

@@ -14,24 +14,22 @@
* limitations under the License.
*/
#define LOG_TAG "Stats_SimpleConditionTracker"
#define DEBUG true // STOPSHIP if true
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);
#include "Log.h"
#include "SimpleConditionTracker.h"
#include <cutils/log.h>
#include <log/logprint.h>
namespace android {
namespace os {
namespace statsd {
using std::string;
using std::unique_ptr;
using std::unordered_map;
using std::vector;
namespace android {
namespace os {
namespace statsd {
SimpleConditionTracker::SimpleConditionTracker(
const string& name, const int index, const SimpleCondition& simpleCondition,
const unordered_map<string, int>& trackerNameIndexMap)

View File

@@ -14,9 +14,10 @@
* limitations under the License.
*/
#include "Log.h"
#include "condition_util.h"
#include <cutils/log.h>
#include <log/event_tag_map.h>
#include <log/log_event_list.h>
#include <log/logprint.h>
@@ -27,14 +28,15 @@
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "stats_util.h"
namespace android {
namespace os {
namespace statsd {
using std::set;
using std::string;
using std::unordered_map;
using std::vector;
namespace android {
namespace os {
namespace statsd {
ConditionState evaluateCombinationCondition(const std::vector<int>& children,
const LogicalOperation& operation,

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config/ConfigKey.h"
#include <sstream>
namespace android {
namespace os {
namespace statsd {
using std::ostringstream;
ConfigKey::ConfigKey() {
}
ConfigKey::ConfigKey(const ConfigKey& that) : mName(that.mName), mUid(that.mUid) {
}
ConfigKey::ConfigKey(int uid, const string& name) : mName(name), mUid(uid) {
}
ConfigKey::~ConfigKey() {
}
string ConfigKey::ToString() const {
ostringstream out;
out << '(' << mUid << ',' << mName << ')';
return out.str();
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include <functional>
#include <iostream>
#include <string>
namespace android {
namespace os {
namespace statsd {
using std::hash;
using std::ostream;
using std::string;
/**
* Uniquely identifies a configuration.
*/
class ConfigKey {
public:
ConfigKey();
explicit ConfigKey(const ConfigKey& that);
ConfigKey(int uid, const string& name);
~ConfigKey();
inline int GetUid() const {
return mUid;
}
inline const string& GetName() const {
return mName;
}
inline bool operator<(const ConfigKey& that) const {
if (mUid < that.mUid) {
return true;
}
if (mUid > that.mUid) {
return false;
}
return mName < that.mName;
};
inline bool operator==(const ConfigKey& that) const {
return mUid == that.mUid && mName == that.mName;
};
string ToString() const;
private:
string mName;
int mUid;
};
inline ostream& operator<<(ostream& os, const ConfigKey& config) {
return os << config.ToString();
}
} // namespace statsd
} // namespace os
} // namespace android
/**
* A hash function for ConfigKey so it can be used for unordered_map/set.
* Unfortunately this hast to go in std namespace because C++ is fun!
*/
namespace std {
using android::os::statsd::ConfigKey;
template <>
struct hash<ConfigKey> {
std::size_t operator()(const ConfigKey& key) const {
return (7 * key.GetUid()) ^ ((hash<string>()(key.GetName())));
}
};
} // namespace std

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config/ConfigListener.h"
namespace android {
namespace os {
namespace statsd {
ConfigListener::ConfigListener() {
}
ConfigListener::~ConfigListener() {
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
#include "config/ConfigKey.h"
#include <utils/RefBase.h>
#include <string>
namespace android {
namespace os {
namespace statsd {
using android::RefBase;
using std::string;
/**
* Callback for different subsystems inside statsd to implement to find out
* when a configuration has been added, updated or removed.
*/
class ConfigListener : public virtual RefBase {
public:
ConfigListener();
virtual ~ConfigListener();
/**
* A configuration was added or updated.
*/
virtual void OnConfigUpdated(const ConfigKey& key, const StatsdConfig& config) = 0;
/**
* A configuration was removed.
*/
virtual void OnConfigRemoved(const ConfigKey& key) = 0;
};
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config/ConfigManager.h"
#include "stats_util.h"
#include <vector>
#include <stdio.h>
namespace android {
namespace os {
namespace statsd {
static StatsdConfig build_fake_config();
ConfigManager::ConfigManager() {
}
ConfigManager::~ConfigManager() {
}
void ConfigManager::Startup() {
// TODO: Implement me -- read from storage and call onto all of the listeners.
// Instead, we'll just make a fake one.
// this should be called from StatsService when it receives a statsd_config
UpdateConfig(ConfigKey(0, "fake"), build_fake_config());
}
void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
mListeners.push_back(listener);
}
void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
// Add to map
mConfigs[key] = config;
// Why doesn't this work? mConfigs.insert({key, config});
// Save to disk
update_saved_configs();
// Tell everyone
for (auto& listener : mListeners) {
listener->OnConfigUpdated(key, config);
}
}
void ConfigManager::RemoveConfig(const ConfigKey& key) {
unordered_map<ConfigKey, StatsdConfig>::iterator it = mConfigs.find(key);
if (it != mConfigs.end()) {
// Remove from map
mConfigs.erase(it);
// Save to disk
update_saved_configs();
// Tell everyone
for (auto& listener : mListeners) {
listener->OnConfigRemoved(key);
}
}
// If we didn't find it, just quietly ignore it.
}
void ConfigManager::RemoveConfigs(int uid) {
vector<ConfigKey> removed;
for (auto it = mConfigs.begin(); it != mConfigs.end();) {
// Remove from map
if (it->first.GetUid() == uid) {
removed.push_back(it->first);
it = mConfigs.erase(it);
} else {
it++;
}
}
// Remove separately so if they do anything in the callback they can't mess up our iteration.
for (auto& key : removed) {
// Tell everyone
for (auto& listener : mListeners) {
listener->OnConfigRemoved(key);
}
}
}
void ConfigManager::Dump(FILE* out) {
fprintf(out, "CONFIGURATIONS (%d)\n", (int)mConfigs.size());
fprintf(out, " uid name\n");
for (unordered_map<ConfigKey, StatsdConfig>::const_iterator it = mConfigs.begin();
it != mConfigs.end(); it++) {
fprintf(out, " %6d %s\n", it->first.GetUid(), it->first.GetName().c_str());
// TODO: Print the contents of the config too.
}
}
void ConfigManager::update_saved_configs() {
// TODO: Implement me -- write to disk.
}
static StatsdConfig build_fake_config() {
// HACK: Hard code a test metric for counting screen on events...
StatsdConfig config;
config.set_config_id(12345L);
// One count metric to count screen on
CountMetric* metric = config.add_count_metric();
metric->set_metric_id(20150717L);
metric->set_what("SCREEN_IS_ON");
metric->mutable_bucket()->set_bucket_size_millis(30 * 1000L);
// One count metric to count PHOTO_CHANGE_OR_CHROME_CRASH
metric = config.add_count_metric();
metric->set_metric_id(20150718L);
metric->set_what("PHOTO_PROCESS_STATE_CHANGE");
metric->mutable_bucket()->set_bucket_size_millis(60 * 1000L);
metric->set_condition("SCREEN_IS_ON");
LogEntryMatcher* eventMatcher = config.add_log_entry_matcher();
eventMatcher->set_name("SCREEN_IS_ON");
SimpleLogEntryMatcher* simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()->set_key(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleLogEntryMatcher->mutable_key_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_log_entry_matcher();
eventMatcher->set_name("SCREEN_IS_OFF");
simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()->set_key(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleLogEntryMatcher->mutable_key_value_matcher(0)->set_eq_int(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
LogEntryMatcher* procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_CRASH");
SimpleLogEntryMatcher* simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
KeyValueMatcher* keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(1002 /*pkg*/);
keyValueMatcher->set_eq_string(
"com.google.android.apps.photos" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
keyValueMatcher->set_eq_int(2);
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_START");
simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(1002 /*pkg*/);
keyValueMatcher->set_eq_string(
"com.google.android.apps.photos" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(1 /*STATE*/);
keyValueMatcher->set_eq_int(1);
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_PROCESS_STATE_CHANGE");
LogEntryMatcher_Combination* combinationMatcher = procEventMatcher->mutable_combination();
combinationMatcher->set_operation(LogicalOperation::OR);
combinationMatcher->add_matcher("PHOTO_START");
combinationMatcher->add_matcher("PHOTO_CRASH");
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("CHROME_CRASH");
simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(1002 /*pkg*/);
keyValueMatcher->set_eq_string(
"com.android.chrome" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(1 /*STATE*/);
keyValueMatcher->set_eq_int(2);
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_CHANGE_OR_CHROME_CRASH");
combinationMatcher = procEventMatcher->mutable_combination();
combinationMatcher->set_operation(LogicalOperation::OR);
combinationMatcher->add_matcher("PHOTO_PROCESS_STATE_CHANGE");
combinationMatcher->add_matcher("CHROME_CRASH");
Condition* condition = config.add_condition();
condition->set_name("SCREEN_IS_ON");
SimpleCondition* simpleCondition = condition->mutable_simple_condition();
simpleCondition->set_start("SCREEN_IS_ON");
simpleCondition->set_stop("SCREEN_IS_OFF");
condition = config.add_condition();
condition->set_name("PHOTO_STARTED");
simpleCondition = condition->mutable_simple_condition();
simpleCondition->set_start("PHOTO_START");
simpleCondition->set_stop("PHOTO_CRASH");
condition = config.add_condition();
condition->set_name("SCREEN_IS_OFF");
simpleCondition = condition->mutable_simple_condition();
simpleCondition->set_start("SCREEN_IS_OFF");
simpleCondition->set_stop("SCREEN_IS_ON");
condition = config.add_condition();
condition->set_name("SCREEN_IS_EITHER_ON_OFF");
Condition_Combination* combination = condition->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_condition("SCREEN_IS_ON");
combination->add_condition("SCREEN_IS_OFF");
condition = config.add_condition();
condition->set_name("SCREEN_IS_NEITHER_ON_OFF");
combination = condition->mutable_combination();
combination->set_operation(LogicalOperation::NOR);
combination->add_condition("SCREEN_IS_ON");
combination->add_condition("SCREEN_IS_OFF");
return config;
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "config/ConfigKey.h"
#include "config/ConfigListener.h"
#include <string>
#include <unordered_map>
#include <stdio.h>
namespace android {
namespace os {
namespace statsd {
using android::RefBase;
using std::string;
using std::unordered_map;
using std::vector;
/**
* Keeps track of which configurations have been set from various sources.
*
* TODO: Store the configs persistently too.
* TODO: Dump method for debugging.
*/
class ConfigManager : public virtual RefBase {
public:
ConfigManager();
virtual ~ConfigManager();
/**
* Call to load the saved configs from disk.
*
* TODO: Implement me
*/
void Startup();
/**
* Someone else wants to know about the configs.
*/
void AddListener(const sp<ConfigListener>& listener);
/**
* A configuration was added or updated.
*
* Reports this to listeners.
*/
void UpdateConfig(const ConfigKey& key, const StatsdConfig& data);
/**
* A configuration was removed.
*
* Reports this to listeners.
*/
void RemoveConfig(const ConfigKey& key);
/**
* Remove all of the configs for the given uid.
*/
void RemoveConfigs(int uid);
/**
* Text dump of our state for debugging.
*/
void Dump(FILE* out);
private:
/**
* Save the configs to disk.
*/
void update_saved_configs();
/**
* The Configs that have been set
*/
unordered_map<ConfigKey, StatsdConfig> mConfigs;
/**
* The ConfigListeners that will be told about changes.
*/
vector<sp<ConfigListener>> mListeners;
};
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -14,13 +14,14 @@
* limitations under the License.
*/
#include "KernelWakelockPuller.h"
#include "Log.h"
#include <android/os/IStatsCompanionService.h>
#include <binder/IPCThreadState.h>
#include <cutils/log.h>
#include <private/android_filesystem_config.h>
#include "StatsPuller.h"
#include "StatsService.h"
#include "external/KernelWakelockPuller.h"
#include "external/StatsPuller.h"
using namespace android;
using namespace android::base;
@@ -40,15 +41,15 @@ String16 KernelWakelockPuller::pull() {
sp<IStatsCompanionService> statsCompanion = StatsService::getStatsCompanionService();
String16 returned_value("");
if (statsCompanion != NULL) {
Status status = statsCompanion->pullData(KernelWakelockPuller::PULL_CODE_KERNEL_WAKELOCKS,
&returned_value);
if (!status.isOk()) {
ALOGW("error pulling kernel wakelock");
}
ALOGD("KernelWakelockPuller::pull succeeded!");
// TODO: remove this when we integrate into aggregation chain.
ALOGD("%s", String8(returned_value).string());
return returned_value;
Status status = statsCompanion->pullData(KernelWakelockPuller::PULL_CODE_KERNEL_WAKELOCKS,
&returned_value);
if (!status.isOk()) {
ALOGW("error pulling kernel wakelock");
}
ALOGD("KernelWakelockPuller::pull succeeded!");
// TODO: remove this when we integrate into aggregation chain.
ALOGD("%s", String8(returned_value).string());
return returned_value;
} else {
ALOGW("statsCompanion not found!");
return String16();

View File

@@ -18,7 +18,7 @@
#define STATSD_KERNELWAKELOCKPULLER_H
#include <utils/String16.h>
#include "StatsPuller.h"
#include "external/StatsPuller.h"
namespace android {
namespace os {

View File

@@ -14,15 +14,13 @@
* limitations under the License.
*/
#define LOG_TAG "StatsPullerManager"
#define DEBUG true
#include "Log.h"
#include "StatsPullerManager.h"
#include <android/os/IStatsCompanionService.h>
#include <cutils/log.h>
#include "StatsService.h"
#include "KernelWakelockPuller.h"
#include "StatsService.h"
#include "external/StatsPullerManager.h"
using namespace android;

View File

@@ -19,7 +19,7 @@
#include <utils/String16.h>
#include <unordered_map>
#include "StatsPuller.h"
#include "external/StatsPuller.h"
namespace android {
namespace os {
@@ -41,7 +41,6 @@ private:
std::unordered_map<int, std::unique_ptr<StatsPuller>> mStatsPullers;
};
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "logd/LogReader.h"
#include <log/log_read.h>
#include <utils/Errors.h>
#include <time.h>
#include <unistd.h>
using namespace android;
using namespace std;
namespace android {
namespace os {
namespace statsd {
LogListener::LogListener() {
}
LogListener::~LogListener() {
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -14,48 +14,29 @@
* limitations under the License.
*/
#ifndef LOG_ENTRY_PRINTER_H
#define LOG_ENTRY_PRINTER_H
#pragma once
#include "LogReader.h"
#include <log/logprint.h>
#include <stdio.h>
#include <log/log_read.h>
#include <utils/RefBase.h>
#include <vector>
namespace android {
namespace os {
namespace statsd {
/**
* Decodes the log entry and prints it to the supplied file descriptor.
* Callback for LogReader
*/
class LogEntryPrinter : public LogListener {
class LogListener : public virtual android::RefBase {
public:
LogEntryPrinter(int out);
virtual ~LogEntryPrinter();
LogListener();
virtual ~LogListener();
virtual void OnLogEvent(const log_msg& msg);
private:
/**
* Where to write to.
*/
int m_out;
/**
* Numeric to string tag name mapping.
*/
EventTagMap* m_tags;
/**
* Pretty printing format.
*/
AndroidLogFormat* m_format;
// TODO: Rather than using log_msg, which doesn't have any real internal structure
// here, we should pull this out into our own LogEntry class.
virtual void OnLogEvent(const log_msg& msg) = 0;
};
} // namespace statsd
} // namespace os
} // namespace android
#endif // LOG_ENTRY_PRINTER_H

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "LogReader.h"
#include "logd/LogReader.h"
#include <log/log_read.h>
@@ -33,24 +33,12 @@ namespace statsd {
#define SNOOZE_INITIAL_MS 100
#define SNOOZE_MAX_MS (10 * 60 * 1000) // Ten minutes
// ================================================================================
LogListener::LogListener() {
}
LogListener::~LogListener() {
}
// ================================================================================
LogReader::LogReader() {
LogReader::LogReader(const sp<LogListener>& listener) : mListener(listener) {
}
LogReader::~LogReader() {
}
void LogReader::AddListener(const sp<LogListener>& listener) {
m_listeners.push_back(listener);
}
void LogReader::Run() {
int nextSnoozeMs = SNOOZE_INITIAL_MS;
@@ -119,11 +107,8 @@ int LogReader::connect_and_read() {
// Record that we read one (used above to know how to snooze).
lineCount++;
// Call the listeners
for (vector<sp<LogListener> >::iterator it = m_listeners.begin();
it != m_listeners.end(); it++) {
(*it)->OnLogEvent(msg);
}
// Call the listener
mListener->OnLogEvent(msg);
}
}

View File

@@ -17,6 +17,8 @@
#ifndef LOGREADER_H
#define LOGREADER_H
#include "logd/LogListener.h"
#include <log/log_read.h>
#include <utils/RefBase.h>
@@ -26,39 +28,21 @@ namespace android {
namespace os {
namespace statsd {
/**
* Callback for LogReader
*/
class LogListener : public virtual android::RefBase {
public:
LogListener();
virtual ~LogListener();
// TODO: Rather than using log_msg, which doesn't have any real internal structure
// here, we should pull this out into our own LogEntry class.
virtual void OnLogEvent(const log_msg& msg) = 0;
};
/**
* Class to read logs from logd.
*/
class LogReader : public virtual android::RefBase {
public:
/**
* Construct the LogReader with a pointer back to the StatsService
* Construct the LogReader with the event listener. (Which is StatsService)
*/
LogReader();
LogReader(const sp<LogListener>& listener);
/**
* Destructor.
*/
virtual ~LogReader();
/**
* Add a LogListener class.
*/
void AddListener(const android::sp<LogListener>& listener);
/**
* Run the main LogReader loop
*/
@@ -66,9 +50,9 @@ public:
private:
/**
* List of listeners to call back on when we do get an event.
* Who is going to get the events when they're read.
*/
std::vector<android::sp<LogListener> > m_listeners;
sp<LogListener> mListener;
/**
* Connect to a single instance of logd, and read until there's a read error.

View File

@@ -14,20 +14,16 @@
* limitations under the License.
*/
#define LOG_TAG "statsd"
#include "Log.h"
#include "LogEntryPrinter.h"
#include "LogReader.h"
#include "StatsLogProcessor.h"
#include "StatsService.h"
#include "UidMap.h"
#include "logd/LogReader.h"
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/Status.h>
#include <cutils/log.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
@@ -53,16 +49,12 @@ struct log_reader_thread_data {
static void* log_reader_thread_func(void* cookie) {
log_reader_thread_data* data = static_cast<log_reader_thread_data*>(cookie);
sp<LogReader> reader = new LogReader();
sp<LogReader> reader = new LogReader(data->service);
// Put the printer one first, so it will print before the real ones.
reader->AddListener(new LogEntryPrinter(STDOUT_FILENO));
sp<StatsLogProcessor> main_processor = new StatsLogProcessor(data->service->getUidMap());
data->service->setProcessor(main_processor);
reader->AddListener(main_processor);
// TODO: Construct and add real LogListners here.
// Tell StatsService that we're ready to go.
data->service->Startup();
// Run the read loop. Never returns.
reader->Run();
ALOGW("statsd LogReader.Run() is not supposed to return.");
@@ -127,6 +119,8 @@ int main(int /*argc*/, char** /*argv*/) {
// TODO: This line is temporary, since statsd doesn't start up automatically (and therefore
// the call in StatsService::SystemRunning() won't ever be called right now).
// TODO: Are you sure? Don't we need to reconnect to the system process if we get restarted?
// --joeo
service->sayHiToStatsCompanion();
// Start the log reader thread

View File

@@ -14,20 +14,21 @@
* limitations under the License.
*/
#include "CombinationLogMatchingTracker.h"
#include "Log.h"
#include "CombinationLogMatchingTracker.h"
#include "matchers/matcher_util.h"
namespace android {
namespace os {
namespace statsd {
#include <cutils/log.h>
#include "matcher_util.h"
using std::set;
using std::string;
using std::unique_ptr;
using std::unordered_map;
using std::vector;
namespace android {
namespace os {
namespace statsd {
CombinationLogMatchingTracker::CombinationLogMatchingTracker(const string& name, const int index)
: LogMatchingTracker(name, index) {
}

View File

@@ -14,23 +14,22 @@
* limitations under the License.
*/
#define LOG_TAG "SimpleLogMatchingTracker"
#define DEBUG true // STOPSHIP if true
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);
#include "Log.h"
#include "SimpleLogMatchingTracker.h"
#include <cutils/log.h>
#include <log/logprint.h>
namespace android {
namespace os {
namespace statsd {
using std::string;
using std::unique_ptr;
using std::unordered_map;
using std::vector;
namespace android {
namespace os {
namespace statsd {
SimpleLogMatchingTracker::SimpleLogMatchingTracker(const string& name, const int index,
const SimpleLogEntryMatcher& matcher)

View File

@@ -14,19 +14,21 @@
* limitations under the License.
*/
#include "matcher_util.h"
#include <cutils/log.h>
#include "Log.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "matchers/LogMatchingTracker.h"
#include "matchers/matcher_util.h"
#include "stats_util.h"
#include <log/event_tag_map.h>
#include <log/log_event_list.h>
#include <log/logprint.h>
#include <utils/Errors.h>
#include <unordered_map>
#include "LogMatchingTracker.h"
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "stats_util.h"
#include <sstream>
#include <unordered_map>
using std::set;
using std::string;

View File

@@ -14,15 +14,14 @@
* limitations under the License.
*/
#define LOG_TAG "CountAnomaly"
#define DEBUG true // STOPSHIP if true
#include "Log.h"
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);
#include "CountAnomalyTracker.h"
#include <cutils/log.h>
namespace android {
namespace os {
namespace statsd {

View File

@@ -14,10 +14,8 @@
* limitations under the License.
*/
#define LOG_TAG "CountMetric"
#define DEBUG true // STOPSHIP if true
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);
#include "Log.h"
#include "CountMetricProducer.h"
#include "CountAnomalyTracker.h"

View File

@@ -17,10 +17,11 @@
#ifndef METRIC_PRODUCER_H
#define METRIC_PRODUCER_H
#include "matchers/matcher_util.h"
#include "packages/PackageInfoListener.h"
#include <log/logprint.h>
#include <utils/RefBase.h>
#include "../matchers/matcher_util.h"
#include "PackageInfoListener.h"
namespace android {
namespace os {

View File

@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "MetricManager"
#define DEBUG true // STOPSHIP if true
#include "Log.h"
#define VLOG(...) \
if (DEBUG) ALOGD(__VA_ARGS__);
#include "MetricsManager.h"
#include <cutils/log.h>
#include <log/logprint.h>
#include "../condition/CombinationConditionTracker.h"
#include "../condition/SimpleConditionTracker.h"

View File

@@ -14,16 +14,15 @@
* limitations under the License.
*/
#ifndef METRICS_MANAGER_H
#define METRICS_MANAGER_H
#pragma once
#include "condition/ConditionTracker.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "matchers/LogMatchingTracker.h"
#include "metrics/MetricProducer.h"
#include <cutils/log.h>
#include <log/logprint.h>
#include <unordered_map>
#include "../condition/ConditionTracker.h"
#include "../matchers/LogMatchingTracker.h"
#include "MetricProducer.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
namespace android {
namespace os {
@@ -94,4 +93,3 @@ private:
} // namespace os
} // namespace android
#endif // METRICS_MANAGER_H

View File

@@ -35,4 +35,4 @@ public:
} // namespace os
} // namespace android
#endif //STATSD_PACKAGE_INFO_LISTENER_H
#endif // STATSD_PACKAGE_INFO_LISTENER_H

View File

@@ -14,8 +14,10 @@
* limitations under the License.
*/
#include "UidMap.h"
#include <cutils/log.h>
#include "Log.h"
#include "packages/UidMap.h"
#include <utils/Errors.h>
using namespace android;
@@ -48,18 +50,18 @@ int UidMap::getAppVersion(int uid, const string& packageName) const {
return 0;
}
void UidMap::updateMap(const vector <int32_t> &uid, const vector <int32_t> &versionCode,
const vector <String16> &packageName) {
lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
void UidMap::updateMap(const vector<int32_t>& uid, const vector<int32_t>& versionCode,
const vector<String16>& packageName) {
lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
mMap.clear();
for (unsigned long j=0; j<uid.size(); j++) {
mMap.insert(make_pair(uid[j], AppData(string(String8(packageName[j]).string()),
versionCode[j])));
for (unsigned long j = 0; j < uid.size(); j++) {
mMap.insert(make_pair(uid[j],
AppData(string(String8(packageName[j]).string()), versionCode[j])));
}
if (mOutput.initial_size() == 0) { // Provide the initial states in the mOutput proto
for (unsigned long j=0; j<uid.size(); j++) {
if (mOutput.initial_size() == 0) { // Provide the initial states in the mOutput proto
for (unsigned long j = 0; j < uid.size(); j++) {
auto t = mOutput.add_initial();
t->set_app(string(String8(packageName[j]).string()));
t->set_version(int(versionCode[j]));
@@ -68,7 +70,7 @@ void UidMap::updateMap(const vector <int32_t> &uid, const vector <int32_t> &vers
}
}
void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int32_t& versionCode){
void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int32_t& versionCode) {
lock_guard<mutex> lock(mMutex);
string app = string(String8(app_16).string());
@@ -80,7 +82,7 @@ void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int32_t
auto log = mOutput.add_changes();
log->set_deletion(false);
//log.timestamp = TODO: choose how timestamps are computed
// log.timestamp = TODO: choose how timestamps are computed
log->set_app(app);
log->set_uid(uid);
log->set_version(versionCode);
@@ -99,15 +101,14 @@ void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int32_t
mMap.insert(make_pair(uid, AppData(app, int(versionCode))));
}
void UidMap::removeApp(const String16& app_16, const int32_t& uid){
void UidMap::removeApp(const String16& app_16, const int32_t& uid) {
lock_guard<mutex> lock(mMutex);
string app = string(String8(app_16).string());
auto log = mOutput.add_changes();
log->set_deletion(true);
//log.timestamp = TODO: choose how timestamps are computed
// log.timestamp = TODO: choose how timestamps are computed
log->set_app(app);
log->set_uid(uid);
@@ -123,19 +124,19 @@ void UidMap::removeApp(const String16& app_16, const int32_t& uid){
}
void UidMap::addListener(sp<PackageInfoListener> producer) {
lock_guard<mutex> lock(mMutex); // Lock for updates
lock_guard<mutex> lock(mMutex); // Lock for updates
mSubscribers.insert(producer);
}
void UidMap::removeListener(sp<PackageInfoListener> producer) {
lock_guard<mutex> lock(mMutex); // Lock for updates
lock_guard<mutex> lock(mMutex); // Lock for updates
mSubscribers.erase(producer);
}
UidMapping UidMap::getAndClearOutput() {
lock_guard<mutex> lock(mMutex); // Lock for updates
lock_guard<mutex> lock(mMutex); // Lock for updates
auto ret = UidMapping(mOutput); // Copy that will be returned.
auto ret = UidMapping(mOutput); // Copy that will be returned.
mOutput.Clear();
// Re-initialize the initial state for the outputs. This results in extra data being uploaded
@@ -154,11 +155,11 @@ void UidMap::printUidMap(FILE* out) {
lock_guard<mutex> lock(mMutex);
for (auto it : mMap) {
fprintf(out, "%s, v%d (%i)\n", it.second.packageName.c_str(), it.second.versionCode, it.first);
fprintf(out, "%s, v%d (%i)\n", it.second.packageName.c_str(), it.second.versionCode,
it.first);
}
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -18,17 +18,17 @@
#define STATSD_UIDMAP_H
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
#include "PackageInfoListener.h"
#include "packages/PackageInfoListener.h"
#include <binder/IResultReceiver.h>
#include <binder/IShellCallback.h>
#include <log/logprint.h>
#include <mutex>
#include <string>
#include <stdio.h>
#include <set>
#include <unordered_map>
#include <utils/RefBase.h>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
using namespace std;
@@ -40,12 +40,12 @@ struct AppData {
const string packageName;
int versionCode;
AppData(const string& a, const int v) : packageName(a), versionCode(v) {};
AppData(const string& a, const int v) : packageName(a), versionCode(v){};
};
// UidMap keeps track of what the corresponding app name (APK name) and version code for every uid
// at any given moment. This map must be updated by StatsCompanionService.
class UidMap : public virtual android::RefBase {
class UidMap : public virtual android::RefBase {
public:
/*
* All three inputs must be the same size, and the jth element in each array refers to the same
@@ -93,5 +93,4 @@ private:
} // namespace os
} // namespace android
#endif //STATSD_UIDMAP_H
#endif // STATSD_UIDMAP_H

View File

@@ -128,162 +128,6 @@ EventMetricData parse(log_msg msg) {
return eventMetricData;
}
StatsdConfig buildFakeConfig() {
// HACK: Hard code a test metric for counting screen on events...
StatsdConfig config;
config.set_config_id(12345L);
// One count metric to count screen on
CountMetric* metric = config.add_count_metric();
metric->set_metric_id(20150717L);
metric->set_what("SCREEN_IS_ON");
metric->mutable_bucket()->set_bucket_size_millis(30 * 1000L);
// One count metric to count PHOTO_CHANGE_OR_CHROME_CRASH
metric = config.add_count_metric();
metric->set_metric_id(20150718L);
metric->set_what("PHOTO_PROCESS_STATE_CHANGE");
metric->mutable_bucket()->set_bucket_size_millis(60 * 1000L);
metric->set_condition("SCREEN_IS_ON");
LogEntryMatcher* eventMatcher = config.add_log_entry_matcher();
eventMatcher->set_name("SCREEN_IS_ON");
SimpleLogEntryMatcher* simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()->set_key(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleLogEntryMatcher->mutable_key_value_matcher(0)->set_eq_int(
2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
eventMatcher = config.add_log_entry_matcher();
eventMatcher->set_name("SCREEN_IS_OFF");
simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()->set_key(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
simpleLogEntryMatcher->mutable_key_value_matcher(0)->set_eq_int(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
LogEntryMatcher* procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_CRASH");
SimpleLogEntryMatcher* simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
KeyValueMatcher* keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(
1002 /*pkg*/);
keyValueMatcher->set_eq_string(
"com.google.android.apps.photos" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(
1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
keyValueMatcher->set_eq_int(2);
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_START");
simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(
1002 /*pkg*/);
keyValueMatcher->set_eq_string(
"com.google.android.apps.photos" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(
1 /*STATE*/);
keyValueMatcher->set_eq_int(1);
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_PROCESS_STATE_CHANGE");
LogEntryMatcher_Combination* combinationMatcher = procEventMatcher->mutable_combination();
combinationMatcher->set_operation(LogicalOperation::OR);
combinationMatcher->add_matcher("PHOTO_START");
combinationMatcher->add_matcher("PHOTO_CRASH");
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("CHROME_CRASH");
simpleLogMatcher2 = procEventMatcher->mutable_simple_log_entry_matcher();
simpleLogMatcher2->add_tag(1112 /*PROCESS_STATE_CHANGE*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(
1002 /*pkg*/);
keyValueMatcher->set_eq_string(
"com.android.chrome" /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
keyValueMatcher = simpleLogMatcher2->add_key_value_matcher();
keyValueMatcher->mutable_key_matcher()->set_key(
1 /*STATE*/);
keyValueMatcher->set_eq_int(2);
procEventMatcher = config.add_log_entry_matcher();
procEventMatcher->set_name("PHOTO_CHANGE_OR_CHROME_CRASH");
combinationMatcher = procEventMatcher->mutable_combination();
combinationMatcher->set_operation(LogicalOperation::OR);
combinationMatcher->add_matcher("PHOTO_PROCESS_STATE_CHANGE");
combinationMatcher->add_matcher("CHROME_CRASH");
Condition* condition = config.add_condition();
condition->set_name("SCREEN_IS_ON");
SimpleCondition* simpleCondition = condition->mutable_simple_condition();
simpleCondition->set_start("SCREEN_IS_ON");
simpleCondition->set_stop("SCREEN_IS_OFF");
condition = config.add_condition();
condition->set_name("PHOTO_STARTED");
simpleCondition = condition->mutable_simple_condition();
simpleCondition->set_start("PHOTO_START");
simpleCondition->set_stop("PHOTO_CRASH");
condition = config.add_condition();
condition->set_name("SCREEN_IS_OFF");
simpleCondition = condition->mutable_simple_condition();
simpleCondition->set_start("SCREEN_IS_OFF");
simpleCondition->set_stop("SCREEN_IS_ON");
condition = config.add_condition();
condition->set_name("SCREEN_IS_EITHER_ON_OFF");
Condition_Combination* combination = condition->mutable_combination();
combination->set_operation(LogicalOperation::OR);
combination->add_condition("SCREEN_IS_ON");
combination->add_condition("SCREEN_IS_OFF");
condition = config.add_condition();
condition->set_name("SCREEN_IS_NEITHER_ON_OFF");
combination = condition->mutable_combination();
combination->set_operation(LogicalOperation::NOR);
combination->add_condition("SCREEN_IS_ON");
combination->add_condition("SCREEN_IS_OFF");
return config;
}
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -16,8 +16,8 @@
#ifndef PARSE_UTIL_H
#define PARSE_UTIL_H
#include "DropboxWriter.h"
#include "LogReader.h"
#include "logd/LogReader.h"
#include "storage/DropboxWriter.h"
#include <log/logprint.h>
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
@@ -30,8 +30,6 @@ EventMetricData parse(log_msg msg);
int getTagId(log_msg msg);
StatsdConfig buildFakeConfig();
} // namespace statsd
} // namespace os
} // namespace android

View File

@@ -17,14 +17,14 @@
#include <android/os/DropBoxManager.h>
#include <androidfw/ZipUtils.h>
#include "DropboxReader.h"
#include "storage/DropboxReader.h"
using android::String16;
using android::ZipUtils;
using android::base::unique_fd;
using android::binder::Status;
using android::os::DropBoxManager;
using android::sp;
using android::String16;
using android::ZipUtils;
using std::vector;
namespace android {

View File

@@ -16,12 +16,12 @@
#include <android/os/DropBoxManager.h>
#include "DropboxWriter.h"
#include "storage/DropboxWriter.h"
using android::String16;
using android::binder::Status;
using android::os::DropBoxManager;
using android::sp;
using android::String16;
using std::vector;
namespace android {

View File

@@ -12,9 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define LOG_TAG "statsd_test"
#include "../src/AnomalyMonitor.h"
#include "anomaly/AnomalyMonitor.h"
#include <gtest/gtest.h>

View File

@@ -12,11 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define LOG_TAG "statsd_test"
#include "condition/condition_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include <gtest/gtest.h>
#include "../src/condition/condition_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include <stdio.h>
#include <vector>

View File

@@ -0,0 +1,156 @@
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/config/ConfigManager.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <iostream>
using namespace android;
using namespace android::os::statsd;
using namespace testing;
using namespace std;
namespace android {
namespace os {
namespace statsd {
static ostream& operator<<(ostream& os, const StatsdConfig& config) {
return os << "StatsdConfig{id=" << config.config_id() << "}";
}
} // namespace statsd
} // namespace os
} // namespace android
/**
* Mock ConfigListener
*/
class MockListener : public ConfigListener {
public:
MOCK_METHOD2(OnConfigUpdated, void(const ConfigKey& key, const StatsdConfig& config));
MOCK_METHOD1(OnConfigRemoved, void(const ConfigKey& key));
};
/**
* Validate that the ConfigKey is the one we wanted.
*/
MATCHER_P2(ConfigKeyEq, uid, name, "") {
return arg.GetUid() == uid && arg.GetName() == name;
}
/**
* Validate that the StatsdConfig is the one we wanted.
*/
MATCHER_P(StatsdConfigEq, configId, "") {
return arg.config_id() == configId;
}
/**
* Test the addOrUpdate and remove methods
*/
TEST(ConfigManagerTest, TestAddUpdateRemove) {
sp<MockListener> listener = new StrictMock<MockListener>();
sp<ConfigManager> manager = new ConfigManager();
manager->AddListener(listener);
StatsdConfig config91;
config91.set_config_id(91);
StatsdConfig config92;
config92.set_config_id(92);
StatsdConfig config93;
config93.set_config_id(93);
StatsdConfig config94;
config94.set_config_id(94);
{
InSequence s;
// The built-in fake one.
// TODO: Remove this when we get rid of the fake one, and make this
// test loading one from disk somewhere.
EXPECT_CALL(*(listener.get()),
OnConfigUpdated(ConfigKeyEq(0, "fake"), StatsdConfigEq(12345)))
.RetiresOnSaturation();
manager->Startup();
// Add another one
EXPECT_CALL(*(listener.get()), OnConfigUpdated(ConfigKeyEq(1, "zzz"), StatsdConfigEq(91)))
.RetiresOnSaturation();
manager->UpdateConfig(ConfigKey(1, "zzz"), config91);
// Update It
EXPECT_CALL(*(listener.get()), OnConfigUpdated(ConfigKeyEq(1, "zzz"), StatsdConfigEq(92)))
.RetiresOnSaturation();
manager->UpdateConfig(ConfigKey(1, "zzz"), config92);
// Add one with the same uid but a different name
EXPECT_CALL(*(listener.get()), OnConfigUpdated(ConfigKeyEq(1, "yyy"), StatsdConfigEq(93)))
.RetiresOnSaturation();
manager->UpdateConfig(ConfigKey(1, "yyy"), config93);
// Add one with the same name but a different uid
EXPECT_CALL(*(listener.get()), OnConfigUpdated(ConfigKeyEq(2, "zzz"), StatsdConfigEq(94)))
.RetiresOnSaturation();
manager->UpdateConfig(ConfigKey(2, "zzz"), config94);
// Remove (1,yyy)
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(1, "yyy")))
.RetiresOnSaturation();
manager->RemoveConfig(ConfigKey(1, "yyy"));
// Remove (2,zzz)
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, "zzz")))
.RetiresOnSaturation();
manager->RemoveConfig(ConfigKey(2, "zzz"));
// Remove (1,zzz)
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(1, "zzz")))
.RetiresOnSaturation();
manager->RemoveConfig(ConfigKey(1, "zzz"));
// Remove (2,zzz) again and we shouldn't get the callback
manager->RemoveConfig(ConfigKey(2, "zzz"));
}
}
/**
* Test removing all of the configs for a uid.
*/
TEST(ConfigManagerTest, TestRemoveUid) {
sp<MockListener> listener = new StrictMock<MockListener>();
sp<ConfigManager> manager = new ConfigManager();
manager->AddListener(listener);
StatsdConfig config;
EXPECT_CALL(*(listener.get()), OnConfigUpdated(_, _)).Times(6);
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, "xxx")));
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, "yyy")));
EXPECT_CALL(*(listener.get()), OnConfigRemoved(ConfigKeyEq(2, "zzz")));
manager->Startup();
manager->UpdateConfig(ConfigKey(1, "aaa"), config);
manager->UpdateConfig(ConfigKey(2, "xxx"), config);
manager->UpdateConfig(ConfigKey(2, "yyy"), config);
manager->UpdateConfig(ConfigKey(2, "zzz"), config);
manager->UpdateConfig(ConfigKey(3, "bbb"), config);
manager->RemoveConfigs(2);
}

View File

@@ -12,15 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define LOG_TAG "statsd_test"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "matchers/matcher_util.h"
#include "stats_util.h"
#include <gtest/gtest.h>
#include <log/log_event_list.h>
#include <log/log_read.h>
#include <log/logprint.h>
#include "../src/matchers/matcher_util.h"
#include "../src/stats_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include <stdio.h>

View File

@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define LOG_TAG "statsd_test"
#include <gtest/gtest.h>
#include <stdio.h>

View File

@@ -12,14 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define LOG_TAG "statsd_test"
#include <gtest/gtest.h>
#include "../src/condition/ConditionTracker.h"
#include "../src/matchers/LogMatchingTracker.h"
#include "../src/metrics/CountMetricProducer.h"
#include "../src/metrics/MetricProducer.h"
#include "../src/metrics/metrics_manager_util.h"
#include "src/condition/ConditionTracker.h"
#include "src/matchers/LogMatchingTracker.h"
#include "src/metrics/CountMetricProducer.h"
#include "src/metrics/MetricProducer.h"
#include "src/metrics/metrics_manager_util.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"

View File

@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define LOG_TAG "statsd_test"
#include "packages/UidMap.h"
#include <gtest/gtest.h>
#include "../src/UidMap.h"
#include <stdio.h>
using namespace android;
@@ -66,4 +66,4 @@ TEST(UidMapTest, TestAddAndRemove) {
}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
#endif

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "../src/indexed_priority_queue.h"
#include "src/anomaly/indexed_priority_queue.h"
#include <gtest/gtest.h>