OSDN Git Service

pull resource power manager stats into statsd
authorChenjie Yu <cjyu@google.com>
Tue, 31 Oct 2017 20:49:36 +0000 (13:49 -0700)
committerChenjie Yu <cjyu@google.com>
Thu, 2 Nov 2017 21:34:05 +0000 (14:34 -0700)
Test: tested on device and check output
Change-Id: I65932a5527d6099e12546b6928a24f3616e54e16

16 files changed:
cmds/statsd/Android.mk
cmds/statsd/src/StatsService.cpp
cmds/statsd/src/StatsService.h
cmds/statsd/src/config/ConfigManager.cpp
cmds/statsd/src/external/ResourcePowerManagerPuller.cpp [new file with mode: 0644]
cmds/statsd/src/external/ResourcePowerManagerPuller.h [moved from cmds/statsd/src/external/KernelWakelockPuller.h with 78% similarity]
cmds/statsd/src/external/StatsCompanionServicePuller.cpp [moved from cmds/statsd/src/external/KernelWakelockPuller.cpp with 63% similarity]
cmds/statsd/src/external/StatsCompanionServicePuller.h [new file with mode: 0644]
cmds/statsd/src/external/StatsPuller.h
cmds/statsd/src/external/StatsPullerManager.cpp
cmds/statsd/src/external/StatsPullerManager.h
cmds/statsd/src/metrics/ValueMetricProducer.cpp
cmds/statsd/src/metrics/ValueMetricProducer.h
cmds/statsd/src/metrics/metrics_manager_util.cpp
cmds/statsd/src/stats_events.proto
services/core/java/com/android/server/stats/StatsCompanionService.java

index 54ade35..c5805fb 100644 (file)
@@ -29,7 +29,8 @@ statsd_common_src := \
     src/config/ConfigKey.cpp \
     src/config/ConfigListener.cpp \
     src/config/ConfigManager.cpp \
-    src/external/KernelWakelockPuller.cpp \
+    src/external/StatsCompanionServicePuller.cpp \
+    src/external/ResourcePowerManagerPuller.cpp \
     src/external/StatsPullerManager.cpp \
     src/logd/LogEvent.cpp \
     src/logd/LogListener.cpp \
@@ -71,7 +72,15 @@ statsd_common_shared_libraries := \
     libutils \
     libservices \
     libandroidfw \
-    libprotoutil
+    libprotoutil \
+    libstatslog \
+    libhardware \
+    libhardware_legacy \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    android.hardware.power@1.0 \
+    android.hardware.power@1.1
 
 # =========
 # statsd
index edb1a0f..11c5de1 100644 (file)
@@ -373,12 +373,15 @@ status_t StatsService::cmd_print_uid_map(FILE* out) {
 
 status_t StatsService::cmd_print_pulled_metrics(FILE* out, const Vector<String8>& args) {
     int s = atoi(args[1].c_str());
-    auto stats = m_stats_puller_manager.Pull(s, time(nullptr));
-    for (const auto& it : stats) {
-        fprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
+    vector<shared_ptr<LogEvent> > stats;
+    if (mStatsPullerManager.Pull(s, &stats)) {
+        for (const auto& it : stats) {
+            fprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
+        }
+        fprintf(out, "Pull from %d: Received %zu elements\n", s, stats.size());
+        return NO_ERROR;
     }
-    fprintf(out, "Pull from %d: Received %zu elements\n", s, stats.size());
-    return NO_ERROR;
+    return UNKNOWN_ERROR;
 }
 
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int32_t>& version,
@@ -440,7 +443,7 @@ Status StatsService::informPollAlarmFired() {
                                          "Only system uid can call informPollAlarmFired");
     }
 
-    m_stats_puller_manager.OnAlarmFired();
+    mStatsPullerManager.OnAlarmFired();
 
     if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
 
index 3930d31..1d7e5a6 100644 (file)
@@ -157,7 +157,7 @@ private:
     /**
      * Fetches external metrics.
      */
-    StatsPullerManager& m_stats_puller_manager = StatsPullerManager::GetInstance();
+    StatsPullerManager& mStatsPullerManager = StatsPullerManager::GetInstance();
 
     /**
      * Tracks the configurations that have been passed to statsd.
index 8812719..890f44b 100644 (file)
@@ -139,7 +139,7 @@ static StatsdConfig build_fake_config() {
     int UID_PROCESS_STATE_TAG_ID = 27;
     int UID_PROCESS_STATE_UID_KEY = 1;
 
-    int KERNEL_WAKELOCK_TAG_ID = 41;
+    int KERNEL_WAKELOCK_TAG_ID = 1004;
     int KERNEL_WAKELOCK_NAME_KEY = 4;
 
     // Count Screen ON events.
@@ -301,6 +301,12 @@ static StatsdConfig build_fake_config() {
     keyValueMatcher->mutable_key_matcher()->set_key(WAKE_LOCK_STATE_KEY);
     keyValueMatcher->set_eq_int(WAKE_LOCK_RELEASE_VALUE);
 
+    // pulled events
+    eventMatcher = config.add_log_entry_matcher();
+    eventMatcher->set_name("KERNEL_WAKELOCK");
+    simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogEntryMatcher->set_tag(KERNEL_WAKELOCK_TAG_ID);
+
     // Conditions.............
     Condition* condition = config.add_condition();
     condition->set_name("SCREEN_IS_ON");
diff --git a/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp b/cmds/statsd/src/external/ResourcePowerManagerPuller.cpp
new file mode 100644 (file)
index 0000000..38953f1
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#define DEBUG true  // STOPSHIP if true
+#include "Log.h"
+
+#include <android/hardware/power/1.0/IPower.h>
+#include <android/hardware/power/1.1/IPower.h>
+#include <fcntl.h>
+#include <hardware/power.h>
+#include <hardware_legacy/power.h>
+#include <inttypes.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "external/ResourcePowerManagerPuller.h"
+#include "external/StatsPuller.h"
+
+#include "logd/LogEvent.h"
+
+using android::hardware::hidl_vec;
+using android::hardware::power::V1_0::IPower;
+using android::hardware::power::V1_0::PowerStatePlatformSleepState;
+using android::hardware::power::V1_0::PowerStateVoter;
+using android::hardware::power::V1_0::Status;
+using android::hardware::power::V1_1::PowerStateSubsystem;
+using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+sp<android::hardware::power::V1_0::IPower> gPowerHalV1_0 = nullptr;
+sp<android::hardware::power::V1_1::IPower> gPowerHalV1_1 = nullptr;
+std::mutex gPowerHalMutex;
+bool gPowerHalExists = true;
+
+static const int power_state_platform_sleep_state_tag = 1011;
+static const int power_state_voter_tag = 1012;
+static const int power_state_subsystem_state_tag = 1013;
+
+bool getPowerHal() {
+    if (gPowerHalExists && gPowerHalV1_0 == nullptr) {
+        gPowerHalV1_0 = android::hardware::power::V1_0::IPower::getService();
+        if (gPowerHalV1_0 != nullptr) {
+            gPowerHalV1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
+            ALOGI("Loaded power HAL service");
+        } else {
+            ALOGW("Couldn't load power HAL service");
+            gPowerHalExists = false;
+        }
+    }
+    return gPowerHalV1_0 != nullptr;
+}
+
+bool ResourcePowerManagerPuller::Pull(const int tagId, vector<shared_ptr<LogEvent>>* data) {
+    std::lock_guard<std::mutex> lock(gPowerHalMutex);
+
+    if (!getPowerHal()) {
+        ALOGE("Power Hal not loaded");
+        return false;
+    }
+
+    data->clear();
+    Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
+            [&data](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
+
+                if (status != Status::SUCCESS) return;
+
+                for (size_t i = 0; i < states.size(); i++) {
+                    const PowerStatePlatformSleepState& state = states[i];
+
+                    auto statePtr = make_shared<LogEvent>(power_state_platform_sleep_state_tag);
+                    auto elemList = statePtr->GetAndroidLogEventList();
+                    *elemList << state.name;
+                    *elemList << state.residencyInMsecSinceBoot;
+                    *elemList << state.totalTransitions;
+                    *elemList << state.supportedOnlyInSuspend;
+                    data->push_back(statePtr);
+
+                    VLOG("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
+                         (long long)state.residencyInMsecSinceBoot,
+                         (long long)state.totalTransitions, state.supportedOnlyInSuspend ? 1 : 0);
+                    for (auto voter : state.voters) {
+                        auto voterPtr = make_shared<LogEvent>(power_state_voter_tag);
+                        auto elemList = voterPtr->GetAndroidLogEventList();
+                        *elemList << state.name;
+                        *elemList << voter.name;
+                        *elemList << voter.totalTimeInMsecVotedForSinceBoot;
+                        *elemList << voter.totalNumberOfTimesVotedSinceBoot;
+                        data->push_back(voterPtr);
+                        VLOG("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
+                             voter.name.c_str(), (long long)voter.totalTimeInMsecVotedForSinceBoot,
+                             (long long)voter.totalNumberOfTimesVotedSinceBoot);
+                    }
+                }
+            });
+    if (!ret.isOk()) {
+        ALOGE("getLowPowerStats() failed: power HAL service not available");
+        gPowerHalV1_0 = nullptr;
+        return false;
+    }
+
+    // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
+    sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
+            android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
+    if (gPowerHal_1_1 != nullptr) {
+        ret = gPowerHal_1_1->getSubsystemLowPowerStats(
+                [&data](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
+
+                    if (status != Status::SUCCESS) return;
+
+                    if (subsystems.size() > 0) {
+                        for (size_t i = 0; i < subsystems.size(); i++) {
+                            const PowerStateSubsystem& subsystem = subsystems[i];
+                            for (size_t j = 0; j < subsystem.states.size(); j++) {
+                                const PowerStateSubsystemSleepState& state = subsystem.states[j];
+                                auto subsystemStatePtr =
+                                        make_shared<LogEvent>(power_state_subsystem_state_tag);
+                                auto elemList = subsystemStatePtr->GetAndroidLogEventList();
+                                *elemList << subsystem.name;
+                                *elemList << state.name;
+                                *elemList << state.residencyInMsecSinceBoot;
+                                *elemList << state.totalTransitions;
+                                *elemList << state.lastEntryTimestampMs;
+                                *elemList << state.supportedOnlyInSuspend;
+                                data->push_back(subsystemStatePtr);
+                                VLOG("subsystemstate: %s, %s, %lld, %lld, %lld",
+                                     subsystem.name.c_str(), state.name.c_str(),
+                                     (long long)state.residencyInMsecSinceBoot,
+                                     (long long)state.totalTransitions,
+                                     (long long)state.lastEntryTimestampMs);
+                            }
+                        }
+                    }
+                });
+    }
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
@@ -23,12 +23,12 @@ namespace android {
 namespace os {
 namespace statsd {
 
-class KernelWakelockPuller : public StatsPuller {
+/**
+ * Reads hal for sleep states
+ */
+class ResourcePowerManagerPuller : public StatsPuller {
 public:
-    // a number of stats need to be pulled from StatsCompanionService
-    //
-    const static int PULL_CODE_KERNEL_WAKELOCKS;
-    vector<StatsLogEventWrapper> Pull() override;
+    bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) override;
 };
 
 }  // namespace statsd
 #include <android/os/IStatsCompanionService.h>
 #include <binder/IPCThreadState.h>
 #include <private/android_filesystem_config.h>
-#include "KernelWakelockPuller.h"
+#include "StatsCompanionServicePuller.h"
 #include "StatsService.h"
 
 using namespace android;
 using namespace android::base;
 using namespace android::binder;
 using namespace android::os;
-using namespace std;
+using std::make_shared;
+using std::shared_ptr;
+using std::vector;
 
 namespace android {
 namespace os {
 namespace statsd {
 
-const int KernelWakelockPuller::PULL_CODE_KERNEL_WAKELOCKS = 1004;
+const int kLogMsgHeaderSize = 28;
 
 // The reading and parsing are implemented in Java. It is not difficult to port over. But for now
 // let StatsCompanionService handle that and send the data back.
-vector<StatsLogEventWrapper> KernelWakelockPuller::Pull() {
+bool StatsCompanionServicePuller::Pull(const int tagId, vector<shared_ptr<LogEvent> >* data) {
     sp<IStatsCompanionService> statsCompanion = StatsService::getStatsCompanionService();
     vector<StatsLogEventWrapper> returned_value;
     if (statsCompanion != NULL) {
-        Status status = statsCompanion->pullData(KernelWakelockPuller::PULL_CODE_KERNEL_WAKELOCKS,
-                                                 &returned_value);
+        Status status = statsCompanion->pullData(tagId, &returned_value);
         if (!status.isOk()) {
             ALOGW("error pulling kernel wakelock");
+            return false;
+        }
+        data->clear();
+        for (const StatsLogEventWrapper& it : returned_value) {
+            log_msg tmp;
+            tmp.entry_v1.len = it.bytes.size();
+            // Manually set the header size to 28 bytes to match the pushed log events.
+            tmp.entry.hdr_size = kLogMsgHeaderSize;
+            // And set the received bytes starting after the 28 bytes reserved for header.
+            std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize);
+            data->push_back(make_shared<LogEvent>(tmp));
         }
         ALOGD("KernelWakelockPuller::pull succeeded!");
-        return returned_value;
+        return true;
     } else {
         ALOGW("statsCompanion not found!");
-        return returned_value;
+        return false;
     }
 }
 
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.h b/cmds/statsd/src/external/StatsCompanionServicePuller.h
new file mode 100644 (file)
index 0000000..3ff2274
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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 <utils/String16.h>
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class StatsCompanionServicePuller : public StatsPuller {
+public:
+    bool Pull(const int tagId, vector<std::shared_ptr<LogEvent> >* data) override;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
index 774e7f0..940ad9c 100644 (file)
@@ -19,6 +19,7 @@
 #include <android/os/StatsLogEventWrapper.h>
 #include <utils/String16.h>
 #include <vector>
+#include "logd/LogEvent.h"
 
 using android::os::StatsLogEventWrapper;
 using std::vector;
@@ -31,7 +32,7 @@ class StatsPuller {
 public:
     virtual ~StatsPuller(){};
 
-    virtual vector<StatsLogEventWrapper> Pull() = 0;
+    virtual bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) = 0;
 };
 
 }  // namespace statsd
index f45cb1c..003b5c4 100644 (file)
 #include <cutils/log.h>
 #include <algorithm>
 #include <climits>
-#include "KernelWakelockPuller.h"
+#include "ResourcePowerManagerPuller.h"
+#include "StatsCompanionServicePuller.h"
 #include "StatsPullerManager.h"
 #include "StatsService.h"
 #include "logd/LogEvent.h"
+#include "statslog.h"
 
 #include <iostream>
 
+using std::map;
 using std::string;
 using std::vector;
+using std::make_shared;
+using std::shared_ptr;
 
 namespace android {
 namespace os {
 namespace statsd {
 
-const int kernel_wakelock = 1;
-const unordered_map<string, int> StatsPullerManager::kPullCodes({{"KERNEL_WAKELOCK",
-                                                                  kernel_wakelock}});
-
 StatsPullerManager::StatsPullerManager()
     : mCurrentPullingInterval(LONG_MAX), mPullStartTimeMs(get_pull_start_time_ms()) {
-    mPullers.insert({kernel_wakelock, make_unique<KernelWakelockPuller>()});
-    mStatsCompanionService = get_stats_companion_service();
-    if (mStatsCompanionService != nullptr) {
-        mStatsCompanionService->cancelPullingAlarms();
-    } else {
-        VLOG("Failed to update pulling interval");
-    }
+    shared_ptr<StatsPuller> statsCompanionServicePuller = make_shared<StatsCompanionServicePuller>();
+    shared_ptr <StatsPuller>
+        resourcePowerManagerPuller = make_shared<ResourcePowerManagerPuller>();
+
+    mPullers.insert({android::util::KERNEL_WAKELOCK_PULLED,
+                     statsCompanionServicePuller});
+    mPullers.insert({android::util::WIFI_BYTES_TRANSFERRED,
+                     statsCompanionServicePuller});
+    mPullers.insert({android::util::MOBILE_BYTES_TRANSFERRED,
+                     statsCompanionServicePuller});
+    mPullers.insert({android::util::WIFI_BYTES_TRANSFERRED_BY_FG_BG,
+                     statsCompanionServicePuller});
+    mPullers.insert({android::util::MOBILE_BYTES_TRANSFERRED_BY_FG_BG,
+                     statsCompanionServicePuller});
+    mPullers.insert({android::util::POWER_STATE_PLATFORM_SLEEP_STATE_PULLED,
+                     resourcePowerManagerPuller});
+    mPullers.insert({android::util::POWER_STATE_VOTER_PULLED,
+                     resourcePowerManagerPuller});
+    mPullers.insert({android::util::POWER_STATE_SUBSYSTEM_SLEEP_STATE_PULLED,
+                     resourcePowerManagerPuller});
+
+    mStatsCompanionService = StatsService::getStatsCompanionService();
 }
 
-static const int log_msg_header_size = 28;
-
-vector<shared_ptr<LogEvent>> StatsPullerManager::Pull(int pullCode, uint64_t timestampSec) {
-    if (DEBUG) ALOGD("Initiating pulling %d", pullCode);
-
-    vector<shared_ptr<LogEvent>> ret;
-    auto itr = mPullers.find(pullCode);
-    if (itr != mPullers.end()) {
-        vector<StatsLogEventWrapper> outputs = itr->second->Pull();
-        for (const StatsLogEventWrapper& it : outputs) {
-            log_msg tmp;
-            tmp.entry_v1.sec = timestampSec;
-            tmp.entry_v1.nsec = 0;
-            tmp.entry_v1.len = it.bytes.size();
-            // Manually set the header size to 28 bytes to match the pushed log events.
-            tmp.entry.hdr_size = log_msg_header_size;
-            // And set the received bytes starting after the 28 bytes reserved for header.
-            copy(it.bytes.begin(), it.bytes.end(), tmp.buf + log_msg_header_size);
-            shared_ptr<LogEvent> evt = make_shared<LogEvent>(tmp);
-            ret.push_back(evt);
-        }
-        return ret;
-    } else {
-        ALOGD("Unknown pull code %d", pullCode);
-        return ret;  // Return early since we don't know what to pull.
-    }
-}
+        bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
+            if (DEBUG) ALOGD("Initiating pulling %d", tagId);
 
-sp<IStatsCompanionService> StatsPullerManager::get_stats_companion_service() {
-    sp<IStatsCompanionService> statsCompanion = nullptr;
-    // Get statscompanion service from service manager
-    const sp<IServiceManager> sm(defaultServiceManager());
-    if (sm != nullptr) {
-        const String16 name("statscompanion");
-        statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
-        if (statsCompanion == nullptr) {
-            ALOGW("statscompanion service unavailable!");
-            return nullptr;
+            if (mPullers.find(tagId) != mPullers.end()) {
+                return mPullers.find(tagId)->second->Pull(tagId, data);
+            } else {
+                ALOGD("Unknown tagId %d", tagId);
+                return false;  // Return early since we don't know what to pull.
+            }
         }
-    }
-    return statsCompanion;
-}
 
 StatsPullerManager& StatsPullerManager::GetInstance() {
     static StatsPullerManager instance;
     return instance;
 }
 
-int StatsPullerManager::GetPullCode(string atomName) {
-    if (kPullCodes.find(atomName) != kPullCodes.end()) {
-        return kPullCodes.find(atomName)->second;
-    } else {
-        return -1;
-    }
+bool StatsPullerManager::PullerForMatcherExists(int tagId) {
+    return mPullers.find(tagId) != mPullers.end();
 }
 
 long StatsPullerManager::get_pull_start_time_ms() {
@@ -111,9 +91,9 @@ long StatsPullerManager::get_pull_start_time_ms() {
     return time(nullptr) * 1000;
 }
 
-void StatsPullerManager::RegisterReceiver(int pullCode, sp<PullDataReceiver> receiver, long intervalMs) {
+void StatsPullerManager::RegisterReceiver(int tagId, sp<PullDataReceiver> receiver, long intervalMs) {
     AutoMutex _l(mReceiversLock);
-    vector<ReceiverInfo>& receivers = mReceivers[pullCode];
+    vector<ReceiverInfo>& receivers = mReceivers[tagId];
     for (auto it = receivers.begin(); it != receivers.end(); it++) {
         if (it->receiver.get() == receiver.get()) {
             VLOG("Receiver already registered of %d", (int)receivers.size());
@@ -135,20 +115,20 @@ void StatsPullerManager::RegisterReceiver(int pullCode, sp<PullDataReceiver> rec
             VLOG("Failed to update pulling interval");
         }
     }
-    VLOG("Puller for pullcode %d registered of %d", pullCode, (int)receivers.size());
+    VLOG("Puller for tagId %d registered of %d", tagId, (int)receivers.size());
 }
 
-void StatsPullerManager::UnRegisterReceiver(int pullCode, sp<PullDataReceiver> receiver) {
+void StatsPullerManager::UnRegisterReceiver(int tagId, sp<PullDataReceiver> receiver) {
     AutoMutex _l(mReceiversLock);
-    if (mReceivers.find(pullCode) == mReceivers.end()) {
-        VLOG("Unknown pull code or no receivers: %d", pullCode);
+    if (mReceivers.find(tagId) == mReceivers.end()) {
+        VLOG("Unknown pull code or no receivers: %d", tagId);
         return;
     }
-    auto& receivers = mReceivers.find(pullCode)->second;
+    auto& receivers = mReceivers.find(tagId)->second;
     for (auto it = receivers.begin(); it != receivers.end(); it++) {
         if (receiver.get() == it->receiver.get()) {
             receivers.erase(it);
-            VLOG("Puller for pullcode %d unregistered of %d", pullCode, (int)receivers.size());
+            VLOG("Puller for tagId %d unregistered of %d", tagId, (int)receivers.size());
             return;
         }
     }
@@ -176,10 +156,12 @@ void StatsPullerManager::OnAlarmFired() {
     }
 
     for (const auto& pullInfo : needToPull) {
-        const vector<shared_ptr<LogEvent>>& data = Pull(pullInfo.first, currentTimeMs/1000);
-        for(const auto& receiverInfo : pullInfo.second) {
-            receiverInfo->receiver->onDataPulled(data);
-            receiverInfo->timeInfo.second = currentTimeMs;
+        vector<shared_ptr<LogEvent>> data;
+        if (Pull(pullInfo.first, &data)) {
+            for (const auto& receiverInfo : pullInfo.second) {
+                receiverInfo->receiver->onDataPulled(data);
+                receiverInfo->timeInfo.second = currentTimeMs;
+            }
         }
     }
 }
index e599b69..67580d6 100644 (file)
@@ -37,44 +37,42 @@ class StatsPullerManager : public virtual RefBase {
 public:
     static StatsPullerManager& GetInstance();
 
-    void RegisterReceiver(int pullCode, sp<PullDataReceiver> receiver, long intervalMs);
+    void RegisterReceiver(int tagId, sp<PullDataReceiver> receiver, long intervalMs);
 
-    void UnRegisterReceiver(int pullCode, sp<PullDataReceiver> receiver);
+    void UnRegisterReceiver(int tagId, sp<PullDataReceiver> receiver);
 
-    // We return a vector of shared_ptr since LogEvent's copy constructor is not available.
-    vector<std::shared_ptr<LogEvent>> Pull(const int pullCode, const uint64_t timestampSec);
-
-    // Translate metric name to pullCodes.
-    // return -1 if no valid pullCode is found
-    int GetPullCode(std::string metricName);
+    // Verify if we know how to pull for this matcher
+    bool PullerForMatcherExists(int tagId);
 
     void OnAlarmFired();
 
+    bool Pull(const int pullCode, vector<std::shared_ptr<LogEvent>>* data);
+
 private:
     StatsPullerManager();
 
+    // use this to update alarm
     sp<IStatsCompanionService> mStatsCompanionService = nullptr;
 
     sp<IStatsCompanionService> get_stats_companion_service();
 
-    std::unordered_map<int, std::unique_ptr<StatsPuller>> mPullers;
-
+    // mapping from simple matcher tagId to puller
+    std::map<int, std::shared_ptr<StatsPuller>> mPullers;
 
-
-      // internal state of a bucket.
       typedef struct {
         // pull_interval_sec : last_pull_time_sec
         std::pair<uint64_t, uint64_t> timeInfo;
         sp<PullDataReceiver> receiver;
       } ReceiverInfo;
 
+    // mapping from simple matcher tagId to receivers
     std::map<int, std::vector<ReceiverInfo>> mReceivers;
 
     Mutex mReceiversLock;
 
     long mCurrentPullingInterval;
 
-    // for value metrics, it is important for the buckets to be aligned to multiple of smallest
+    // for pulled metrics, it is important for the buckets to be aligned to multiple of smallest
     // bucket size. All pulled metrics start pulling based on this time, so that they can be
     // correctly attributed to the correct buckets. Pulled data attach a timestamp which is the
     // request time.
@@ -83,10 +81,8 @@ private:
     long get_pull_start_time_ms();
 
     LogEvent parse_pulled_data(String16 data);
-
-    static const std::unordered_map<std::string, int> kPullCodes;
 };
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
index cb6166d..ca33371 100644 (file)
@@ -36,11 +36,11 @@ namespace statsd {
 
 // ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
 ValueMetricProducer::ValueMetricProducer(const ValueMetric& metric, const int conditionIndex,
-                                         const sp<ConditionWizard>& wizard)
+                                         const sp<ConditionWizard>& wizard, const int pullTagId)
     : MetricProducer((time(nullptr) / 600 * 600 * NANO_SECONDS_IN_A_SECOND), conditionIndex,
                      wizard),
       mMetric(metric),
-      mPullCode(mStatsPullerManager.GetPullCode(mMetric.what())) {
+      mPullTagId(pullTagId) {
   // TODO: valuemetric for pushed events may need unlimited bucket length
   mBucketSizeNs = mMetric.bucket().bucket_size_millis() * 1000 * 1000;
 
@@ -52,8 +52,8 @@ ValueMetricProducer::ValueMetricProducer(const ValueMetric& metric, const int co
     mConditionSliced = true;
   }
 
-  if (!metric.has_condition() && mPullCode != -1) {
-    mStatsPullerManager.RegisterReceiver(mPullCode, this, metric.bucket().bucket_size_millis());
+  if (!metric.has_condition() && mPullTagId != -1) {
+    mStatsPullerManager.RegisterReceiver(mPullTagId, this, metric.bucket().bucket_size_millis());
   }
 
   VLOG("value metric %lld created. bucket size %lld start_time: %lld", metric.metric_id(),
@@ -120,27 +120,27 @@ StatsLogReport ValueMetricProducer::onDumpReport() {
 void ValueMetricProducer::onConditionChanged(const bool condition, const uint64_t eventTime) {
     mCondition = condition;
 
-    if (mPullCode != -1) {
-        vector<shared_ptr<LogEvent>> allData = mStatsPullerManager.Pull(mPullCode, eventTime);
+    if (mPullTagId != -1) {
         if (mCondition == true) {
-            mStatsPullerManager.RegisterReceiver(mPullCode, this,
+            mStatsPullerManager.RegisterReceiver(mPullTagId, this,
                                                  mMetric.bucket().bucket_size_millis());
         } else if (mCondition == ConditionState::kFalse) {
-            mStatsPullerManager.UnRegisterReceiver(mPullCode, this);
+            mStatsPullerManager.UnRegisterReceiver(mPullTagId, this);
         }
-        if (allData.size() == 0) {
-            return;
-        }
-        AutoMutex _l(mLock);
-        if (allData.size() == 0) {
-            return;
-        }
-        for (const auto& data : allData) {
-            onMatchedLogEvent(0, *data, false);
+
+        vector<shared_ptr<LogEvent>> allData;
+        if (mStatsPullerManager.Pull(mPullTagId, &allData)) {
+            if (allData.size() == 0) {
+                return;
+            }
+            AutoMutex _l(mLock);
+            for (const auto& data : allData) {
+                onMatchedLogEvent(0, *data, false);
+            }
+            flush_if_needed(eventTime);
         }
-        flush_if_needed(eventTime);
+        return;
     }
-    return;
 }
 
 void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
@@ -188,7 +188,7 @@ void ValueMetricProducer::onMatchedLogEventInternal(
       }
     }
   }
-  if (mPullCode == -1) {
+  if (mPullTagId == -1) {
       flush_if_needed(eventTimeNs);
   }
 }
index 4f17913..8653981 100644 (file)
@@ -33,7 +33,7 @@ namespace statsd {
 class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
 public:
     ValueMetricProducer(const ValueMetric& valueMetric, const int conditionIndex,
-                        const sp<ConditionWizard>& wizard);
+                        const sp<ConditionWizard>& wizard, const int pullTagId);
 
     virtual ~ValueMetricProducer();
 
@@ -67,7 +67,8 @@ private:
 
     Mutex mLock;
 
-    const int mPullCode;
+    // tagId for pulled data. -1 if this is not pulled
+    const int mPullTagId;
 
     // internal state of a bucket.
     typedef struct {
index 3d4036e..3ff2a77 100644 (file)
@@ -192,12 +192,12 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
                  unordered_map<int, std::vector<int>>& trackerToMetricMap) {
     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
     const int allMetricsCount =
-            config.count_metric_size() + config.duration_metric_size() + config.event_metric_size();
+            config.count_metric_size() + config.duration_metric_size() + config.event_metric_size() + config.value_metric_size();
     allMetricProducers.reserve(allMetricsCount);
     StatsPullerManager& statsPullerManager = StatsPullerManager::GetInstance();
 
     // Build MetricProducers for each metric defined in config.
-    // (1) build CountMetricProducer
+    // build CountMetricProducer
     for (int i = 0; i < config.count_metric_size(); i++) {
         const CountMetric& metric = config.count_metric(i);
         if (!metric.has_what()) {
@@ -224,6 +224,7 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
         allMetricProducers.push_back(countProducer);
     }
 
+    // build DurationMetricProducer
     for (int i = 0; i < config.duration_metric_size(); i++) {
         int metricIndex = allMetricProducers.size();
         const DurationMetric& metric = config.duration_metric(i);
@@ -285,6 +286,7 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
         allMetricProducers.push_back(durationMetric);
     }
 
+    // build EventMetricProducer
     for (int i = 0; i < config.event_metric_size(); i++) {
         int metricIndex = allMetricProducers.size();
         const EventMetric& metric = config.event_metric(i);
@@ -310,7 +312,7 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
         allMetricProducers.push_back(eventMetric);
     }
 
-    // value metrics
+    // build ValueMetricProducer
     for (int i = 0; i < config.value_metric_size(); i++) {
         const ValueMetric& metric = config.value_metric(i);
         if (!metric.has_what()) {
@@ -318,24 +320,35 @@ bool initMetrics(const StatsdConfig& config, const unordered_map<string, int>& l
             return false;
         }
 
-        int pullCode = statsPullerManager.GetPullCode(metric.what());
-        if (pullCode == -1) {
-            ALOGW("cannot find %s in pulled metrics", metric.what().c_str());
+        int metricIndex = allMetricProducers.size();
+        int trackerIndex;
+        if (!handleMetricWithLogTrackers(metric.what(), metricIndex, metric.dimension_size() > 0,
+                                         allLogEntryMatchers, logTrackerMap, trackerToMetricMap,
+                                         trackerIndex)) {
             return false;
         }
 
-        sp<MetricProducer> valueProducer;
-        auto condition_it = conditionTrackerMap.find(metric.condition());
-        if (condition_it == conditionTrackerMap.end()) {
-            ALOGW("cannot find the Condition %s in the config", metric.condition().c_str());
-            return false;
+        sp<LogMatchingTracker> atomMatcher = allLogEntryMatchers.at(trackerIndex);
+        // If it is pulled atom, it should be simple matcher with one tagId.
+        int pullTagId = -1;
+        for (int tagId : atomMatcher->getTagIds()) {
+            if (statsPullerManager.PullerForMatcherExists(tagId)) {
+                if (atomMatcher->getTagIds().size() != 1) {
+                    return false;
+                }
+                pullTagId = tagId;
+            }
+        }
+
+        int conditionIndex = -1;
+        if (metric.has_condition()) {
+            handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+                                       metric.links(), allConditionTrackers, conditionIndex,
+                                       conditionToMetricMap);
         }
-        int metricIndex = allMetricProducers.size();
-        valueProducer = new ValueMetricProducer(metric, condition_it->second, wizard);
-        // will create new vector if not exist before.
-        auto& metricList = conditionToMetricMap[condition_it->second];
-        metricList.push_back(metricIndex);
 
+        sp<MetricProducer> valueProducer =
+                new ValueMetricProducer(metric, conditionIndex, wizard, pullTagId);
         allMetricProducers.push_back(valueProducer);
     }
     return true;
index 51244c6..82d9759 100644 (file)
@@ -72,6 +72,7 @@ message StatsEvent {
         PhoneSignalStrengthChanged phone_signal_strength_changed = 40;
         SettingChanged setting_changed = 41;
         ActivityForegroundStateChanged activity_foreground_state_changed = 42;
+
         // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
     }
 
@@ -81,7 +82,10 @@ message StatsEvent {
         WifiBytesTransferredByFgBg wifi_bytes_transferred_by_fg_bg = 1001;
         MobileBytesTransferred mobile_bytes_transferred = 1002;
         MobileBytesTransferredByFgBg mobile_bytes_transferred_by_fg_bg = 1003;
-        KernelWakelocksReported kernel_wakelocks_reported = 1004;
+        KernelWakelockPulled kernel_wakelock_pulled = 1004;
+        PowerStatePlatformSleepStatePulled power_state_platform_sleep_state_pulled = 1005;
+        PowerStateVoterPulled power_state_voter_pulled = 1006;
+        PowerStateSubsystemSleepStatePulled power_state_subsystem_sleep_state_pulled = 1007;
     }
 }
 
@@ -794,7 +798,7 @@ message MobileBytesTransferredByFgBg {
  * Pulled from:
  *   StatsCompanionService using KernelWakelockReader.
  */
-message KernelWakelocksReported {
+message KernelWakelockPulled {
     optional string name = 1;
 
     optional int32 count = 2;
@@ -803,3 +807,44 @@ message KernelWakelocksReported {
 
     optional int64 time = 4;
 }
+
+/*
+ * Pulls PowerStatePlatformSleepState.
+ *
+ * Definition here:
+ *   hardware/interfaces/power/1.0/types.hal
+ */
+message PowerStatePlatformSleepStatePulled {
+    optional string name = 1;
+    optional uint64 residency_in_msec_since_boot = 2;
+    optional uint64 total_transitions = 3;
+    optional bool supported_only_in_suspend = 4;
+}
+
+/**
+ * Pulls PowerStateVoter.
+ *
+ * Definition here:
+ *   hardware/interfaces/power/1.0/types.hal
+ */
+message PowerStateVoterPulled {
+    optional string power_state_platform_sleep_state_name = 1;
+    optional string power_state_voter_name = 2;
+    optional uint64 total_time_in_msec_voted_for_since_boot = 3;
+    optional uint64 total_number_of_times_voted_since_boot = 4;
+}
+
+/**
+ * Pulls PowerStateSubsystemSleepState.
+ *
+ * Definition here:
+ *   hardware/interfaces/power/1.1/types.hal
+ */
+message PowerStateSubsystemSleepStatePulled {
+    optional string power_state_subsystem_name = 1;
+    optional string power_state_subsystem_sleep_state_name = 2;
+    optional uint64 residency_in_msec_since_boot = 3;
+    optional uint64 total_transitions = 4;
+    optional uint64 last_entry_timestamp_ms = 5;
+    optional bool supported_only_in_suspend = 6;
+}
index 41534cb..2488723 100644 (file)
@@ -286,10 +286,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
       }
     }
 
-    // These values must be kept in sync with cmd/statsd/StatsPullerManager.h.
-    // TODO: pull the constant from stats_events.proto instead
-    private static final int PULL_CODE_KERNEL_WAKELOCKS = 20;
-
     private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
 
@@ -347,12 +343,12 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
     }
 
     @Override // Binder call
-    public StatsLogEventWrapper[] pullData(int pullCode) {
+    public StatsLogEventWrapper[] pullData(int tagId) {
         enforceCallingPermission();
         if (DEBUG)
-            Slog.d(TAG, "Pulling " + pullCode);
+            Slog.d(TAG, "Pulling " + tagId);
 
-        switch (pullCode) {
+        switch (tagId) {
             case StatsLog.WIFI_BYTES_TRANSFERRED: {
                 long token = Binder.clearCallingIdentity();
                 try {
@@ -366,7 +362,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                     // Combine all the metrics per Uid into one record.
                     NetworkStats stats = nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
                             NetworkStats.TAG_NONE, null).groupedByUid();
-                    return addNetworkStats(pullCode, stats, false);
+                    return addNetworkStats(tagId, stats, false);
                 } catch (java.io.IOException e) {
                     Slog.e(TAG, "Pulling netstats for wifi bytes has error", e);
                 } finally {
@@ -386,7 +382,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                     // Combine all the metrics per Uid into one record.
                     NetworkStats stats = nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
                         NetworkStats.TAG_NONE, null).groupedByUid();
-                    return addNetworkStats(pullCode, stats, false);
+                    return addNetworkStats(tagId, stats, false);
                 } catch (java.io.IOException e) {
                     Slog.e(TAG, "Pulling netstats for mobile bytes has error", e);
                 } finally {
@@ -406,7 +402,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                     NetworkStats stats = rollupNetworkStatsByFGBG(
                             nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
                             NetworkStats.TAG_NONE, null));
-                    return addNetworkStats(pullCode, stats, true);
+                    return addNetworkStats(tagId, stats, true);
                 } catch (java.io.IOException e) {
                     Slog.e(TAG, "Pulling netstats for wifi bytes w/ fg/bg has error", e);
                 } finally {
@@ -426,7 +422,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                     NetworkStats stats = rollupNetworkStatsByFGBG(
                             nsf.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
                             NetworkStats.TAG_NONE, null));
-                    return addNetworkStats(pullCode, stats, true);
+                    return addNetworkStats(tagId, stats, true);
                 } catch (java.io.IOException e) {
                     Slog.e(TAG, "Pulling netstats for mobile bytes w/ fg/bg has error", e);
                 } finally {
@@ -434,14 +430,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                 }
                 break;
             }
-            case StatsLog.KERNEL_WAKELOCKS_REPORTED: {
+            case StatsLog.KERNEL_WAKELOCK_PULLED: {
                 final KernelWakelockStats wakelockStats =
                         mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
                 List<StatsLogEventWrapper> ret = new ArrayList();
                 for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
                     String name = ent.getKey();
                     KernelWakelockStats.Entry kws = ent.getValue();
-                    StatsLogEventWrapper e = new StatsLogEventWrapper(pullCode, 4);
+                    StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, 4);
                     e.writeString(name);
                     e.writeInt(kws.mCount);
                     e.writeInt(kws.mVersion);
@@ -451,7 +447,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                 return ret.toArray(new StatsLogEventWrapper[ret.size()]);
             }
             default:
-                Slog.w(TAG, "No such pollable data as " + pullCode);
+                Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
         }
         return null;