Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a98bd998 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Captures metrics on disk when devices reboot and shutdown. Specifically,"

parents 40a910f3 947fbce5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ statsd_common_src := \
    src/packages/UidMap.cpp \
    src/storage/DropboxReader.cpp \
    src/storage/DropboxWriter.cpp \
    src/storage/StorageManager.cpp \
    src/StatsLogProcessor.cpp \
    src/StatsService.cpp \
    src/stats_util.cpp \
+43 −5
Original line number Diff line number Diff line
@@ -17,14 +17,19 @@
#include "Log.h"
#include "statslog.h"

#include <android-base/file.h>
#include <dirent.h>
#include "StatsLogProcessor.h"
#include "android-base/stringprintf.h"
#include "metrics/CountMetricProducer.h"
#include "stats_util.h"
#include "storage/StorageManager.h"

#include <log/log_event_list.h>
#include <utils/Errors.h>

using namespace android;
using android::base::StringPrintf;
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
using android::util::FIELD_TYPE_FLOAT;
@@ -41,18 +46,25 @@ namespace android {
namespace os {
namespace statsd {

// for ConfigMetricsReport
// for ConfigMetricsReportList
const int FIELD_ID_CONFIG_KEY = 1;
const int FIELD_ID_METRICS = 2;
const int FIELD_ID_UID_MAP = 3;
const int FIELD_ID_REPORTS = 2;
// for ConfigKey
const int FIELD_ID_UID = 1;
const int FIELD_ID_NAME = 2;
// for ConfigMetricsReport
const int FIELD_ID_METRICS = 1;
const int FIELD_ID_UID_MAP = 2;

#define STATS_DATA_DIR "/data/system/stats-data"

StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
                                     const sp<AnomalyMonitor>& anomalyMonitor,
                                     const std::function<void(const ConfigKey&)>& sendBroadcast)
    : mUidMap(uidMap), mAnomalyMonitor(anomalyMonitor), mSendBroadcast(sendBroadcast) {
    // On each initialization of StatsLogProcessor, check stats-data directory to see if there is
    // any left over data to be read.
    StorageManager::sendBroadcast(STATS_DATA_DIR, mSendBroadcast);
}

StatsLogProcessor::~StatsLogProcessor() {
@@ -138,13 +150,19 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outD

    ProtoOutputStream proto;

    // Fill in ConfigKey.
    // Start of ConfigKey.
    long long configKeyToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
    proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid());
    proto.write(FIELD_TYPE_STRING | FIELD_ID_NAME, key.GetName());
    proto.end(configKeyToken);
    // End of ConfigKey.

    // Fill in StatsLogReport's.
    // Start of ConfigMetricsReport (reports).
    long long reportsToken =
            proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);

    // First, fill in ConfigMetricsReport using current data on memory, which
    // starts from filling in StatsLogReport's.
    for (auto& m : it->second->onDumpReport()) {
        // Add each vector of StatsLogReport into a repeated field.
        proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS,
@@ -158,6 +176,13 @@ void StatsLogProcessor::onDumpReport(const ConfigKey& key, vector<uint8_t>* outD
    uidMap.SerializeToArray(&uidMapBuffer[0], uidMapSize);
    proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP, uidMapBuffer, uidMapSize);

    // End of ConfigMetricsReport (reports).
    proto.end(reportsToken);

    // Then, check stats-data directory to see there's any file containing
    // ConfigMetricsReport from previous shutdowns to concatenate to reports.
    StorageManager::appendConfigMetricsReport(STATS_DATA_DIR, proto);

    if (outData != nullptr) {
        outData->clear();
        outData->resize(proto.size());
@@ -207,6 +232,19 @@ void StatsLogProcessor::flushIfNecessary(uint64_t timestampNs,
    }
}

void StatsLogProcessor::WriteDataToDisk() {
    mkdir(STATS_DATA_DIR, S_IRWXU);
    for (auto& pair : mMetricsManagers) {
        const ConfigKey& key = pair.first;
        vector<uint8_t> data;
        onDumpReport(key, &data);
        // TODO: Add a guardrail to prevent accumulation of file on disk.
        string file_name = StringPrintf("%s/%d-%s-%ld", STATS_DATA_DIR, key.GetUid(),
                                        key.GetName().c_str(), time(nullptr));
        StorageManager::writeFile(file_name.c_str(), &data[0], data.size());
    }
}

}  // namespace statsd
}  // namespace os
}  // namespace android
+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ public:
            const uint64_t timestampNs,
            unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> anomalySet);

    /* Flushes data to disk. Data on memory will be gone after written to disk. */
    void WriteDataToDisk();

private:
    mutable mutex mBroadcastTimesMutex;

+31 −17
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "config/ConfigManager.h"
#include "guardrail/MemoryLeakTrackUtil.h"
#include "storage/DropboxReader.h"
#include "storage/StorageManager.h"

#include <android-base/file.h>
#include <binder/IPCThreadState.h>
@@ -75,7 +76,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
    mUidMap = new UidMap();
    mConfigManager = new ConfigManager();
    mProcessor = new StatsLogProcessor(mUidMap, mAnomalyMonitor, [this](const ConfigKey& key) {
        auto sc = getStatsCompanionService();
        sp<IStatsCompanionService> sc = getStatsCompanionService();
        auto receiver = mConfigManager->GetConfigReceiver(key);
        if (sc == nullptr) {
            ALOGD("Could not find StatsCompanionService");
@@ -231,6 +232,10 @@ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>&
        if (!args[0].compare(String8("meminfo"))) {
            return cmd_dump_memory_info(out);
        }

        if (!args[0].compare(String8("write-to-disk"))) {
            return cmd_write_data_to_disk(out);
        }
    }

    print_cmd_help(out);
@@ -267,6 +272,11 @@ void StatsService::print_cmd_help(FILE* out) {
    fprintf(out, "  Prints the output of a pulled metrics source (int indicates source)\n");
    fprintf(out, "\n");
    fprintf(out, "\n");
    fprintf(out, "usage: adb shell cmd stats write-to-disk \n");
    fprintf(out, "\n");
    fprintf(out, "  Flushes all data on memory to disk.\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");
@@ -487,6 +497,12 @@ status_t StatsService::cmd_print_uid_map(FILE* out) {
    return NO_ERROR;
}

status_t StatsService::cmd_write_data_to_disk(FILE* out) {
    fprintf(out, "Writing data to disk\n");
    mProcessor->WriteDataToDisk();
    return NO_ERROR;
}

status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) {
    int s = atoi(args[1].c_str());
    vector<shared_ptr<LogEvent> > stats;
@@ -502,22 +518,7 @@ status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>

status_t StatsService::cmd_remove_config_files(FILE* out) {
    fprintf(out, "Trying to remove config files...\n");
    unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir);
    if (dir == NULL) {
        fprintf(out, "No existing config files found exiting...\n");
        return NO_ERROR;
    }

    dirent* de;
    while ((de = readdir(dir.get()))) {
        char* name = de->d_name;
        if (name[0] == '.') continue;
        string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name);
        fprintf(out, "Deleting file %s\n", file_name.c_str());
        if (remove(file_name.c_str())) {
            fprintf(out, "Error deleting file %s\n", file_name.c_str());
        }
    }
    StorageManager::deleteAllFiles(STATS_SERVICE_DIR);
    return NO_ERROR;
}

@@ -611,6 +612,19 @@ Status StatsService::systemRunning() {
    return Status::ok();
}

Status StatsService::writeDataToDisk() {
    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
        return Status::fromExceptionCode(Status::EX_SECURITY,
                                         "Only system uid can call systemRunning");
    }

    ALOGD("StatsService::writeDataToDisk");

    mProcessor->WriteDataToDisk();

    return Status::ok();
}

void StatsService::sayHiToStatsCompanion() {
    // TODO: This method needs to be private. It is temporarily public and unsecured for testing
    // purposes.
+6 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public:
                                    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 writeDataToDisk();

    /**
     * Called right before we start processing events.
@@ -150,6 +151,11 @@ private:
     */
    status_t cmd_print_uid_map(FILE* out);

    /**
     * Flush the data to disk.
     */
    status_t cmd_write_data_to_disk(FILE* out);

    /**
     * Print contents of a pulled metrics source.
     */
Loading