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 \
libutils \
libservices \
libandroidfw \
- libprotoutil
+ libprotoutil \
+ libstatslog \
+ libhardware \
+ libhardware_legacy \
+ libhidlbase \
+ libhidltransport \
+ libhwbinder \
+ android.hardware.power@1.0 \
+ android.hardware.power@1.1
# =========
# statsd
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,
"Only system uid can call informPollAlarmFired");
}
- m_stats_puller_manager.OnAlarmFired();
+ mStatsPullerManager.OnAlarmFired();
if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded");
/**
* Fetches external metrics.
*/
- StatsPullerManager& m_stats_puller_manager = StatsPullerManager::GetInstance();
+ StatsPullerManager& mStatsPullerManager = StatsPullerManager::GetInstance();
/**
* Tracks the configurations that have been passed to statsd.
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.
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");
--- /dev/null
+/*
+ * 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
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;
}
}
--- /dev/null
+/*
+ * 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
#include <android/os/StatsLogEventWrapper.h>
#include <utils/String16.h>
#include <vector>
+#include "logd/LogEvent.h"
using android::os::StatsLogEventWrapper;
using std::vector;
public:
virtual ~StatsPuller(){};
- virtual vector<StatsLogEventWrapper> Pull() = 0;
+ virtual bool Pull(const int tagId, vector<std::shared_ptr<LogEvent>>* data) = 0;
};
} // namespace statsd
#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() {
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());
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;
}
}
}
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;
+ }
}
}
}
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.
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
// 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;
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(),
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) {
}
}
}
- if (mPullCode == -1) {
+ if (mPullTagId == -1) {
flush_if_needed(eventTimeNs);
}
}
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();
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 {
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()) {
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);
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);
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()) {
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;
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.
}
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;
}
}
* Pulled from:
* StatsCompanionService using KernelWakelockReader.
*/
-message KernelWakelocksReported {
+message KernelWakelockPulled {
optional string name = 1;
optional int32 count = 2;
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;
+}
}
}
- // 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();
}
@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 {
// 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 {
// 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 {
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 {
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 {
}
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);
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;