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:
@@ -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
30
cmds/statsd/src/Log.h
Normal 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__);
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
47
cmds/statsd/src/config/ConfigKey.cpp
Normal file
47
cmds/statsd/src/config/ConfigKey.cpp
Normal 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
|
||||
94
cmds/statsd/src/config/ConfigKey.h
Normal file
94
cmds/statsd/src/config/ConfigKey.h
Normal 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
|
||||
31
cmds/statsd/src/config/ConfigListener.cpp
Normal file
31
cmds/statsd/src/config/ConfigListener.cpp
Normal 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
|
||||
54
cmds/statsd/src/config/ConfigListener.h
Normal file
54
cmds/statsd/src/config/ConfigListener.h
Normal 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
|
||||
251
cmds/statsd/src/config/ConfigManager.cpp
Normal file
251
cmds/statsd/src/config/ConfigManager.cpp
Normal 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
|
||||
102
cmds/statsd/src/config/ConfigManager.h
Normal file
102
cmds/statsd/src/config/ConfigManager.h
Normal 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
|
||||
@@ -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();
|
||||
@@ -18,7 +18,7 @@
|
||||
#define STATSD_KERNELWAKELOCKPULLER_H
|
||||
|
||||
#include <utils/String16.h>
|
||||
#include "StatsPuller.h"
|
||||
#include "external/StatsPuller.h"
|
||||
|
||||
namespace android {
|
||||
namespace os {
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
41
cmds/statsd/src/logd/LogListener.cpp
Normal file
41
cmds/statsd/src/logd/LogListener.cpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -35,4 +35,4 @@ public:
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
|
||||
#endif //STATSD_PACKAGE_INFO_LISTENER_H
|
||||
#endif // STATSD_PACKAGE_INFO_LISTENER_H
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
156
cmds/statsd/tests/ConfigManager_test.cpp
Normal file
156
cmds/statsd/tests/ConfigManager_test.cpp
Normal 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);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user