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

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

Merge "Persist active metrics to disk and read back"

parents 1c267874 c7939cba
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ cc_defaults {

    srcs: [
        ":statsd_aidl",
        "src/active_config_list.proto",
        "src/statsd_config.proto",
        "src/FieldValue.cpp",
        "src/hash.cpp",
+76 −3
Original line number Diff line number Diff line
@@ -20,12 +20,13 @@

#include <android-base/file.h>
#include <dirent.h>
#include <frameworks/base/cmds/statsd/src/active_config_list.pb.h>
#include "StatsLogProcessor.h"
#include "stats_log_util.h"
#include "android-base/stringprintf.h"
#include "external/StatsPullerManager.h"
#include "guardrail/StatsdStats.h"
#include "metrics/CountMetricProducer.h"
#include "external/StatsPullerManager.h"
#include "stats_log_util.h"
#include "stats_util.h"
#include "storage/StorageManager.h"

@@ -67,9 +68,17 @@ const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6;
const int FIELD_ID_DUMP_REPORT_REASON = 8;
const int FIELD_ID_STRINGS = 9;

const int FIELD_ID_ACTIVE_CONFIG_LIST = 1;
const int FIELD_ID_CONFIG_ID = 1;
const int FIELD_ID_CONFIG_UID = 2;
const int FIELD_ID_ACTIVE_METRIC = 3;
const int FIELD_ID_METRIC_ID = 1;
const int FIELD_ID_TIME_TO_LIVE_NANOS = 2;

#define NS_PER_HOUR 3600 * NS_PER_SEC

#define STATS_DATA_DIR "/data/misc/stats-data"
#define STATS_ACTIVE_METRIC_DIR "/data/misc/stats-active-metric"

// Cool down period for writing data to disk to avoid overwriting files.
#define WRITE_DATA_COOL_DOWN_SEC 5
@@ -507,6 +516,70 @@ void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key,
    mOnDiskDataConfigs.insert(key);
}

void StatsLogProcessor::WriteMetricsActivationToDisk(int64_t currentTimeNs) {
    std::lock_guard<std::mutex> lock(mMetricsMutex);
    ProtoOutputStream proto;

    for (const auto& pair : mMetricsManagers) {
        uint64_t activeConfigListToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
                                                     FIELD_ID_ACTIVE_CONFIG_LIST);
        proto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_ID, (long long)pair.first.GetId());
        proto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_UID, pair.first.GetUid());

        vector<const MetricProducer*> acrtiveMetrics;
        pair.second->getActiveMetrics(acrtiveMetrics);
        for (const MetricProducer* metric : acrtiveMetrics) {
            if (metric->isActive()) {
                uint64_t metricToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
                                                   FIELD_ID_ACTIVE_METRIC);
                proto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID,
                            (long long)metric->getMetricId());
                proto.write(FIELD_TYPE_INT64 | FIELD_ID_TIME_TO_LIVE_NANOS,
                            (long long)metric->getRemainingTtlNs(currentTimeNs));
                proto.end(metricToken);
            }
        }
        proto.end(activeConfigListToken);
    }

    string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR);
    StorageManager::deleteFile(file_name.c_str());
    android::base::unique_fd fd(
            open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
    if (fd == -1) {
        ALOGE("Attempt to write %s but failed", file_name.c_str());
        return;
    }
    proto.flush(fd.get());
}

void StatsLogProcessor::LoadMetricsActivationFromDisk() {
    string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR);
    int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
    if (fd != -1) {
        string content;
        if (android::base::ReadFdToString(fd, &content)) {
            ActiveConfigList activeConfigList;
            if (activeConfigList.ParseFromString(content)) {
                for (int i = 0; i < activeConfigList.active_config_size(); i++) {
                    const auto& config = activeConfigList.active_config(i);
                    ConfigKey key(config.uid(), config.config_id());
                    auto it = mMetricsManagers.find(key);
                    if (it == mMetricsManagers.end()) {
                        ALOGE("No config found for config %s", key.ToString().c_str());
                        continue;
                    }
                    VLOG("Setting active config %s", key.ToString().c_str());
                    it->second->setActiveMetrics(config, mTimeBaseNs);
                }
            }
            VLOG("Successfully loaded %d active configs.", activeConfigList.active_config_size());
        }
        close(fd);
    }
    StorageManager::deleteFile(file_name.c_str());
}

void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) {
    const int64_t timeNs = getElapsedRealtimeNs();
    // Do not write to disk if we already have in the last few seconds.
+8 −0
Original line number Diff line number Diff line
@@ -80,6 +80,12 @@ public:
    /* Flushes data to disk. Data on memory will be gone after written to disk. */
    void WriteDataToDisk(const DumpReportReason dumpReportReason);

    /* Persist metric activation status onto disk. */
    void WriteMetricsActivationToDisk(int64_t currentTimeNs);

    /* Load metric activation status from disk. */
    void LoadMetricsActivationFromDisk();

    // Reset all configs.
    void resetConfigs();

@@ -188,6 +194,8 @@ private:
    FRIEND_TEST(StatsLogProcessorTest, TestRateLimitByteSize);
    FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
    FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
    FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);

    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
    FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3);
+4 −1
Original line number Diff line number Diff line
@@ -161,7 +161,8 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
    mConfigManager = new ConfigManager();
    mProcessor = new StatsLogProcessor(
            mUidMap, mPullerManager, mAnomalyAlarmMonitor, mPeriodicAlarmMonitor,
            getElapsedRealtimeNs(), [this](const ConfigKey& key) {
            getElapsedRealtimeNs(),
            [this](const ConfigKey& key) {
                sp<IStatsCompanionService> sc = getStatsCompanionService();
                auto receiver = mConfigManager->GetConfigReceiver(key);
                if (sc == nullptr) {
@@ -867,6 +868,7 @@ Status StatsService::informDeviceShutdown() {
    ENFORCE_UID(AID_SYSTEM);
    VLOG("StatsService::informDeviceShutdown");
    mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN);
    mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs());
    return Status::ok();
}

@@ -901,6 +903,7 @@ Status StatsService::statsCompanionReady() {

void StatsService::Startup() {
    mConfigManager->Startup();
    mProcessor->LoadMetricsActivationFromDisk();
}

void StatsService::Terminate() {
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */

syntax = "proto2";

package android.os.statsd;
option java_package = "com.android.os";
option java_multiple_files = true;
option java_outer_classname = "ActiveConfigProto";

message ActiveMetric {
    // metric id
    optional int64 metric_id = 1;
    // Remaining time to live in nano seconds. -1 for infinity.
    optional int64 time_to_live_nanos = 2;
}

message ActiveConfig {
    // config id
    optional int64 config_id = 1;
    // config uid
    optional int32 uid = 2;
    // metrics
    repeated ActiveMetric active_metric = 3;
}

// all configs and their metrics on device.
message ActiveConfigList {
    repeated ActiveConfig active_config = 1;
}
 No newline at end of file
Loading