Loading cmds/statsd/src/external/StatsCompanionServicePuller.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* da } data->clear(); for (const StatsLogEventWrapper& it : returned_value) { LogEvent::createLogEvents(it, *data); data->push_back(make_shared<LogEvent>(it)); } VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId); return true; Loading cmds/statsd/src/external/StatsPuller.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -32,10 +32,9 @@ using std::lock_guard; sp<UidMap> StatsPuller::mUidMap = nullptr; void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; } // ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently StatsPuller::StatsPuller(const int tagId) : mTagId(tagId) { // Pullers can cause significant impact to system health and battery. // So that we don't pull too frequently. mCoolDownNs = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.coolDownNs; VLOG("Puller for tag %d created. Cooldown set to %lld", mTagId, (long long)mCoolDownNs); } Loading Loading @@ -65,7 +64,7 @@ bool StatsPuller::Pull(const int64_t elapsedTimeNs, std::vector<std::shared_ptr< data->setLogdWallClockTimestampNs(wallClockTimeNs); } if (ret && mCachedData.size() > 0) { mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId); mergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId); (*data) = mCachedData; } StatsdStats::getInstance().notePullDelay(mTagId, getElapsedRealtimeNs() - elapsedTimeNs); Loading cmds/statsd/src/external/StatsPullerManager.cpp +66 −29 Original line number Diff line number Diff line Loading @@ -54,42 +54,52 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // wifi_bytes_transfer {android::util::WIFI_BYTES_TRANSFER, {{2, 3, 4, 5}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}}, // wifi_bytes_transfer_by_fg_bg {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, {{3, 4, 5, 6}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}}, // mobile_bytes_transfer {android::util::MOBILE_BYTES_TRANSFER, {{2, 3, 4, 5}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}}, // mobile_bytes_transfer_by_fg_bg {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, {{3, 4, 5, 6}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}}, // bluetooth_bytes_transfer {android::util::BLUETOOTH_BYTES_TRANSFER, {{2, 3}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}}, // kernel_wakelock {android::util::KERNEL_WAKELOCK, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, // subsystem_sleep_state {android::util::SUBSYSTEM_SLEEP_STATE, {{}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}}, {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}}, // on_device_power_measurement {android::util::ON_DEVICE_POWER_MEASUREMENT, {{}, 1 * NS_PER_SEC, new PowerStatsPuller()}}, {android::util::ON_DEVICE_POWER_MEASUREMENT, {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}}, // cpu_time_per_freq {android::util::CPU_TIME_PER_FREQ, {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, {{3}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, // cpu_time_per_uid {android::util::CPU_TIME_PER_UID, {{2, 3}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}}, // cpu_time_per_uid_freq Loading @@ -97,135 +107,162 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader {android::util::CPU_TIME_PER_UID_FREQ, {{4}, {2, 3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}}, // cpu_active_time // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader {android::util::CPU_ACTIVE_TIME, {{2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}}, {{2}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}}, // cpu_cluster_time // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader {android::util::CPU_CLUSTER_TIME, {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}}, {{3}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}}, // wifi_activity_energy_info {android::util::WIFI_ACTIVITY_INFO, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}}, // modem_activity_info {android::util::MODEM_ACTIVITY_INFO, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, // bluetooth_activity_info {android::util::BLUETOOTH_ACTIVITY_INFO, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}}, // system_elapsed_realtime {android::util::SYSTEM_ELAPSED_REALTIME, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}}, // system_uptime {android::util::SYSTEM_UPTIME, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, // remaining_battery_capacity {android::util::REMAINING_BATTERY_CAPACITY, {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}}, // full_battery_capacity {android::util::FULL_BATTERY_CAPACITY, {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}}, // battery_voltage {android::util::BATTERY_VOLTAGE, {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}}, // battery_level {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}}, // battery_voltage {android::util::BATTERY_LEVEL, {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}}, {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}}, // process_memory_state {android::util::PROCESS_MEMORY_STATE, {{4, 5, 6, 7, 8, 9}, {2, 3, 10}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}}, // native_process_memory_state {android::util::NATIVE_PROCESS_MEMORY_STATE, {{3, 4, 5, 6}, {2, 7}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}}, {android::util::PROCESS_MEMORY_HIGH_WATER_MARK, {{3}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}}, // temperature {android::util::TEMPERATURE, {{}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}}, {android::util::TEMPERATURE, {{}, {}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}}, // binder_calls {android::util::BINDER_CALLS, {{4, 5, 6, 8, 12}, {2, 3, 7, 9, 10, 11, 13}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BINDER_CALLS)}}, // binder_calls_exceptions {android::util::BINDER_CALLS_EXCEPTIONS, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}, // looper_stats {android::util::LOOPER_STATS, {{5, 6, 7, 8, 9}, {2, 3, 4, 10}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::LOOPER_STATS)}}, // Disk Stats {android::util::DISK_STATS, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}}, // Directory usage {android::util::DIRECTORY_USAGE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}}, // Size of app's code, data, and cache {android::util::APP_SIZE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}}, // Size of specific categories of files. Eg. Music. {android::util::CATEGORY_SIZE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, // Number of fingerprints registered to each user. {android::util::NUM_FINGERPRINTS, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}}, // ProcStats. {android::util::PROC_STATS, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}}, // ProcStatsPkgProc. {android::util::PROC_STATS_PKG_PROC, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}}, // Disk I/O stats per uid. {android::util::DISK_IO, {{2,3,4,5,6,7,8,9,10,11}, {}, 3 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_IO)}}, // PowerProfile constants for power model calculations. {android::util::POWER_PROFILE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}}, // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses. {android::util::PROCESS_CPU_TIME, {{} /* additive fields */, {{} /* additive fields */, {} /* non additive fields */, 5 * NS_PER_SEC /* min cool-down in seconds*/, new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}}, {android::util::CPU_TIME_PER_THREAD_FREQ, {{7}, {2, 3, 4, 5, 6}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}}, // DeviceCalculatedPowerUse. {android::util::DEVICE_CALCULATED_POWER_USE, {{}, 1 * NS_PER_SEC, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}}, // DeviceCalculatedPowerBlameUid. {android::util::DEVICE_CALCULATED_POWER_BLAME_UID, {{}, // BatteryStats already merged isolated with host ids so it's unnecessary here. {{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here. 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}}, // DeviceCalculatedPowerBlameOther. {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER, {{}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}}, // BuildInformation. Loading cmds/statsd/src/external/StatsPullerManager.h +3 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ typedef struct { // The field numbers of the fields that need to be summed when merging // isolated uid with host uid. std::vector<int> additiveFields; // The field numbers of the fields that can't be merged when merging // data belong to isolated uid and host uid. std::vector<int> nonAdditiveFields; // How long should the puller wait before doing an actual pull again. Default // 1 sec. Set this to 0 if this is handled elsewhere. int64_t coolDownNs = 1 * NS_PER_SEC; Loading cmds/statsd/src/external/puller_util.cpp +98 −98 Original line number Diff line number Diff line Loading @@ -25,13 +25,67 @@ namespace android { namespace os { namespace statsd { using std::list; using std::map; using std::set; using std::shared_ptr; using std::sort; using std::vector; namespace { bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs, const vector<int>& nonAdditiveFields) { const auto& l_values = lhs->getValues(); const auto& r_values = rhs->getValues(); for (size_t i : nonAdditiveFields) { // We store everything starting from index 0, so we need to use i-1 if (!(l_values.size() > i - 1 && r_values.size() > i - 1 && l_values[i - 1].mValue == r_values[i - 1].mValue)) { return false; } } return true; } // merge rhs to lhs // when calling this function, all sanity check should be done already. // e.g., index boundary, nonAdditiveFields matching etc. bool mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs, const vector<int>& additiveFields) { vector<FieldValue>* host_values = lhs->getMutableValues(); const auto& child_values = rhs->getValues(); for (int i : additiveFields) { Value& host = (*host_values)[i - 1].mValue; const Value& child = (child_values[i - 1]).mValue; if (child.getType() != host.getType()) { return false; } switch (child.getType()) { case INT: host.setInt(host.int_value + child.int_value); break; case LONG: host.setLong(host.long_value + child.long_value); break; default: ALOGE("Tried to merge 2 fields with unsupported type"); return false; } } return true; } bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<int>& host_pos, const vector<int>& nonAdditiveFields, const vector<int>& additiveFields) { for (const auto& pos : host_pos) { if (shouldMerge(data[pos], data[child_pos], nonAdditiveFields) && mergeEvent(data[pos], data[child_pos], additiveFields)) { return true; } } return false; } } // namespace /** * Process all data and merge isolated with host if necessary. * For example: Loading @@ -41,7 +95,7 @@ using std::vector; * int byte_send = 3; * int byte_recv = 4; * } * additive fields are {3, 4} * additive fields are {3, 4}, non-additive field is {2} * If we pulled the following events (uid1_child is an isolated uid which maps to uid1): * [uid1, fg, 100, 200] * [uid1_child, fg, 100, 200] Loading @@ -50,119 +104,65 @@ using std::vector; * We want to merge them and results should be: * [uid1, fg, 200, 400] * [uid1, bg, 100, 200] * * All atoms should be of the same tagId. All fields should be present. */ void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap, void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap, int tagId) { if (StatsPullerManager::kAllPullAtomInfo.find(tagId) == StatsPullerManager::kAllPullAtomInfo.end()) { VLOG("Unknown pull atom id %d", tagId); return; } if ((android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) == android::util::AtomsInfo::kAtomsWithAttributionChain.end()) && (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) == android::util::AtomsInfo::kAtomsWithUidField.end())) { VLOG("No uid or attribution chain to merge, atom %d", tagId); int uidField; auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId); if (it == android::util::AtomsInfo::kAtomsWithUidField.end()) { VLOG("No uid to merge for atom %d", tagId); return; } else { uidField = it->second; // uidField is the field number in proto, } const vector<int>& additiveFields = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields; const vector<int>& nonAdditiveFields = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.nonAdditiveFields; // 1. Map all isolated uid in-place to host uid for (shared_ptr<LogEvent>& event : data) { if (event->GetTagId() != tagId) { ALOGE("Wrong atom. Expecting %d, got %d", tagId, event->GetTagId()); return; } if (android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) != android::util::AtomsInfo::kAtomsWithAttributionChain.end()) { for (auto& value : *(event->getMutableValues())) { if (value.mField.getPosAtDepth(0) > kAttributionField) { break; } if (isAttributionUidField(value)) { const int hostUid = uidMap->getHostUidOrSelf(value.mValue.int_value); value.mValue.setInt(hostUid); // map of host uid to their position in the original vector map<int, vector<int>> hostPosition; vector<bool> toRemove = vector<bool>(data.size(), false); for (size_t i = 0; i < data.size(); i++) { vector<FieldValue>* valueList = data[i]->getMutableValues(); int uid; if (uidField > 0 && (int)data[i]->getValues().size() >= uidField && (data[i]->getValues())[uidField - 1].mValue.getType() == INT) { uid = (*data[i]->getMutableValues())[uidField - 1].mValue.int_value; } else { ALOGE("Malformed log, uid not found. %s", data[i]->ToString().c_str()); continue; } const int hostUid = uidMap->getHostUidOrSelf(uid); if (hostUid != uid) { (*valueList)[0].mValue.setInt(hostUid); } if (hostPosition.find(hostUid) == hostPosition.end()) { hostPosition[hostUid].push_back(i); } else { auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId); if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) { int uidField = it->second; // uidField is the field number in proto, // starting from 1 if (uidField > 0 && (int)event->getValues().size() >= uidField && (event->getValues())[uidField - 1].mValue.getType() == INT) { Value& value = (*event->getMutableValues())[uidField - 1].mValue; const int hostUid = uidMap->getHostUidOrSelf(value.int_value); value.setInt(hostUid); if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) { toRemove[i] = true; } else { ALOGE("Malformed log, uid not found. %s", event->ToString().c_str()); return; } hostPosition[hostUid].push_back(i); } } } // 2. sort the data, bit-wise sort(data.begin(), data.end(), [](const shared_ptr<LogEvent>& lhs, const shared_ptr<LogEvent>& rhs) { if (lhs->size() != rhs->size()) { return lhs->size() < rhs->size(); } const std::vector<FieldValue>& lhsValues = lhs->getValues(); const std::vector<FieldValue>& rhsValues = rhs->getValues(); for (int i = 0; i < (int)lhs->size(); i++) { if (lhsValues[i] != rhsValues[i]) { return lhsValues[i] < rhsValues[i]; } } return false; }); vector<shared_ptr<LogEvent>> mergedData; const vector<int>& additiveFieldsVec = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields; const set<int> additiveFields(additiveFieldsVec.begin(), additiveFieldsVec.end()); bool needMerge = true; // 3. do the merge. // The loop invariant is this: for every event, check if it differs on // non-additive fields, or have different attribution chain length. // If so, no need to merge, add itself to the result. // Otherwise, merge the value onto the one immediately next to it. for (int i = 0; i < (int)data.size() - 1; i++) { // Size different, must be different chains. if (data[i]->size() != data[i + 1]->size()) { for (size_t i = 0; i < toRemove.size(); i++) { if (!toRemove[i]) { mergedData.push_back(data[i]); continue; } vector<FieldValue>* lhsValues = data[i]->getMutableValues(); vector<FieldValue>* rhsValues = data[i + 1]->getMutableValues(); needMerge = true; for (int p = 0; p < (int)lhsValues->size(); p++) { if ((*lhsValues)[p] != (*rhsValues)[p]) { int pos = (*lhsValues)[p].mField.getPosAtDepth(0); // Differ on non-additive field, abort. if (additiveFields.find(pos) == additiveFields.end()) { needMerge = false; break; } } } if (!needMerge) { mergedData.push_back(data[i]); continue; } // This should be infrequent operation. for (int p = 0; p < (int)lhsValues->size(); p++) { int pos = (*lhsValues)[p].mField.getPosAtDepth(0); if (additiveFields.find(pos) != additiveFields.end()) { (*rhsValues)[p].mValue += (*lhsValues)[p].mValue; } } } mergedData.push_back(data.back()); data.clear(); data = mergedData; } Loading Loading
cmds/statsd/src/external/StatsCompanionServicePuller.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* da } data->clear(); for (const StatsLogEventWrapper& it : returned_value) { LogEvent::createLogEvents(it, *data); data->push_back(make_shared<LogEvent>(it)); } VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId); return true; Loading
cmds/statsd/src/external/StatsPuller.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -32,10 +32,9 @@ using std::lock_guard; sp<UidMap> StatsPuller::mUidMap = nullptr; void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; } // ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently StatsPuller::StatsPuller(const int tagId) : mTagId(tagId) { // Pullers can cause significant impact to system health and battery. // So that we don't pull too frequently. mCoolDownNs = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.coolDownNs; VLOG("Puller for tag %d created. Cooldown set to %lld", mTagId, (long long)mCoolDownNs); } Loading Loading @@ -65,7 +64,7 @@ bool StatsPuller::Pull(const int64_t elapsedTimeNs, std::vector<std::shared_ptr< data->setLogdWallClockTimestampNs(wallClockTimeNs); } if (ret && mCachedData.size() > 0) { mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId); mergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId); (*data) = mCachedData; } StatsdStats::getInstance().notePullDelay(mTagId, getElapsedRealtimeNs() - elapsedTimeNs); Loading
cmds/statsd/src/external/StatsPullerManager.cpp +66 −29 Original line number Diff line number Diff line Loading @@ -54,42 +54,52 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // wifi_bytes_transfer {android::util::WIFI_BYTES_TRANSFER, {{2, 3, 4, 5}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}}, // wifi_bytes_transfer_by_fg_bg {android::util::WIFI_BYTES_TRANSFER_BY_FG_BG, {{3, 4, 5, 6}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}}, // mobile_bytes_transfer {android::util::MOBILE_BYTES_TRANSFER, {{2, 3, 4, 5}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}}, // mobile_bytes_transfer_by_fg_bg {android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG, {{3, 4, 5, 6}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}}, // bluetooth_bytes_transfer {android::util::BLUETOOTH_BYTES_TRANSFER, {{2, 3}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}}, // kernel_wakelock {android::util::KERNEL_WAKELOCK, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}}, // subsystem_sleep_state {android::util::SUBSYSTEM_SLEEP_STATE, {{}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}}, {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}}, // on_device_power_measurement {android::util::ON_DEVICE_POWER_MEASUREMENT, {{}, 1 * NS_PER_SEC, new PowerStatsPuller()}}, {android::util::ON_DEVICE_POWER_MEASUREMENT, {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}}, // cpu_time_per_freq {android::util::CPU_TIME_PER_FREQ, {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, {{3}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}}, // cpu_time_per_uid {android::util::CPU_TIME_PER_UID, {{2, 3}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}}, // cpu_time_per_uid_freq Loading @@ -97,135 +107,162 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader {android::util::CPU_TIME_PER_UID_FREQ, {{4}, {2, 3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}}, // cpu_active_time // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader {android::util::CPU_ACTIVE_TIME, {{2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}}, {{2}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}}, // cpu_cluster_time // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader {android::util::CPU_CLUSTER_TIME, {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}}, {{3}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}}, // wifi_activity_energy_info {android::util::WIFI_ACTIVITY_INFO, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}}, // modem_activity_info {android::util::MODEM_ACTIVITY_INFO, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}}, // bluetooth_activity_info {android::util::BLUETOOTH_ACTIVITY_INFO, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}}, // system_elapsed_realtime {android::util::SYSTEM_ELAPSED_REALTIME, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}}, // system_uptime {android::util::SYSTEM_UPTIME, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}}, // remaining_battery_capacity {android::util::REMAINING_BATTERY_CAPACITY, {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}}, // full_battery_capacity {android::util::FULL_BATTERY_CAPACITY, {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}}, // battery_voltage {android::util::BATTERY_VOLTAGE, {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}}, // battery_level {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}}, // battery_voltage {android::util::BATTERY_LEVEL, {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}}, {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}}, // process_memory_state {android::util::PROCESS_MEMORY_STATE, {{4, 5, 6, 7, 8, 9}, {2, 3, 10}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}}, // native_process_memory_state {android::util::NATIVE_PROCESS_MEMORY_STATE, {{3, 4, 5, 6}, {2, 7}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}}, {android::util::PROCESS_MEMORY_HIGH_WATER_MARK, {{3}, {2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}}, // temperature {android::util::TEMPERATURE, {{}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}}, {android::util::TEMPERATURE, {{}, {}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}}, // binder_calls {android::util::BINDER_CALLS, {{4, 5, 6, 8, 12}, {2, 3, 7, 9, 10, 11, 13}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BINDER_CALLS)}}, // binder_calls_exceptions {android::util::BINDER_CALLS_EXCEPTIONS, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}, // looper_stats {android::util::LOOPER_STATS, {{5, 6, 7, 8, 9}, {2, 3, 4, 10}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::LOOPER_STATS)}}, // Disk Stats {android::util::DISK_STATS, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}}, // Directory usage {android::util::DIRECTORY_USAGE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}}, // Size of app's code, data, and cache {android::util::APP_SIZE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}}, // Size of specific categories of files. Eg. Music. {android::util::CATEGORY_SIZE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, // Number of fingerprints registered to each user. {android::util::NUM_FINGERPRINTS, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}}, // ProcStats. {android::util::PROC_STATS, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}}, // ProcStatsPkgProc. {android::util::PROC_STATS_PKG_PROC, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}}, // Disk I/O stats per uid. {android::util::DISK_IO, {{2,3,4,5,6,7,8,9,10,11}, {}, 3 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_IO)}}, // PowerProfile constants for power model calculations. {android::util::POWER_PROFILE, {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}}, // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses. {android::util::PROCESS_CPU_TIME, {{} /* additive fields */, {{} /* additive fields */, {} /* non additive fields */, 5 * NS_PER_SEC /* min cool-down in seconds*/, new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}}, {android::util::CPU_TIME_PER_THREAD_FREQ, {{7}, {2, 3, 4, 5, 6}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}}, // DeviceCalculatedPowerUse. {android::util::DEVICE_CALCULATED_POWER_USE, {{}, 1 * NS_PER_SEC, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}}, // DeviceCalculatedPowerBlameUid. {android::util::DEVICE_CALCULATED_POWER_BLAME_UID, {{}, // BatteryStats already merged isolated with host ids so it's unnecessary here. {{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here. 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}}, // DeviceCalculatedPowerBlameOther. {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER, {{}, {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}}, // BuildInformation. Loading
cmds/statsd/src/external/StatsPullerManager.h +3 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ typedef struct { // The field numbers of the fields that need to be summed when merging // isolated uid with host uid. std::vector<int> additiveFields; // The field numbers of the fields that can't be merged when merging // data belong to isolated uid and host uid. std::vector<int> nonAdditiveFields; // How long should the puller wait before doing an actual pull again. Default // 1 sec. Set this to 0 if this is handled elsewhere. int64_t coolDownNs = 1 * NS_PER_SEC; Loading
cmds/statsd/src/external/puller_util.cpp +98 −98 Original line number Diff line number Diff line Loading @@ -25,13 +25,67 @@ namespace android { namespace os { namespace statsd { using std::list; using std::map; using std::set; using std::shared_ptr; using std::sort; using std::vector; namespace { bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs, const vector<int>& nonAdditiveFields) { const auto& l_values = lhs->getValues(); const auto& r_values = rhs->getValues(); for (size_t i : nonAdditiveFields) { // We store everything starting from index 0, so we need to use i-1 if (!(l_values.size() > i - 1 && r_values.size() > i - 1 && l_values[i - 1].mValue == r_values[i - 1].mValue)) { return false; } } return true; } // merge rhs to lhs // when calling this function, all sanity check should be done already. // e.g., index boundary, nonAdditiveFields matching etc. bool mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs, const vector<int>& additiveFields) { vector<FieldValue>* host_values = lhs->getMutableValues(); const auto& child_values = rhs->getValues(); for (int i : additiveFields) { Value& host = (*host_values)[i - 1].mValue; const Value& child = (child_values[i - 1]).mValue; if (child.getType() != host.getType()) { return false; } switch (child.getType()) { case INT: host.setInt(host.int_value + child.int_value); break; case LONG: host.setLong(host.long_value + child.long_value); break; default: ALOGE("Tried to merge 2 fields with unsupported type"); return false; } } return true; } bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<int>& host_pos, const vector<int>& nonAdditiveFields, const vector<int>& additiveFields) { for (const auto& pos : host_pos) { if (shouldMerge(data[pos], data[child_pos], nonAdditiveFields) && mergeEvent(data[pos], data[child_pos], additiveFields)) { return true; } } return false; } } // namespace /** * Process all data and merge isolated with host if necessary. * For example: Loading @@ -41,7 +95,7 @@ using std::vector; * int byte_send = 3; * int byte_recv = 4; * } * additive fields are {3, 4} * additive fields are {3, 4}, non-additive field is {2} * If we pulled the following events (uid1_child is an isolated uid which maps to uid1): * [uid1, fg, 100, 200] * [uid1_child, fg, 100, 200] Loading @@ -50,119 +104,65 @@ using std::vector; * We want to merge them and results should be: * [uid1, fg, 200, 400] * [uid1, bg, 100, 200] * * All atoms should be of the same tagId. All fields should be present. */ void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap, void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap, int tagId) { if (StatsPullerManager::kAllPullAtomInfo.find(tagId) == StatsPullerManager::kAllPullAtomInfo.end()) { VLOG("Unknown pull atom id %d", tagId); return; } if ((android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) == android::util::AtomsInfo::kAtomsWithAttributionChain.end()) && (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) == android::util::AtomsInfo::kAtomsWithUidField.end())) { VLOG("No uid or attribution chain to merge, atom %d", tagId); int uidField; auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId); if (it == android::util::AtomsInfo::kAtomsWithUidField.end()) { VLOG("No uid to merge for atom %d", tagId); return; } else { uidField = it->second; // uidField is the field number in proto, } const vector<int>& additiveFields = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields; const vector<int>& nonAdditiveFields = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.nonAdditiveFields; // 1. Map all isolated uid in-place to host uid for (shared_ptr<LogEvent>& event : data) { if (event->GetTagId() != tagId) { ALOGE("Wrong atom. Expecting %d, got %d", tagId, event->GetTagId()); return; } if (android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) != android::util::AtomsInfo::kAtomsWithAttributionChain.end()) { for (auto& value : *(event->getMutableValues())) { if (value.mField.getPosAtDepth(0) > kAttributionField) { break; } if (isAttributionUidField(value)) { const int hostUid = uidMap->getHostUidOrSelf(value.mValue.int_value); value.mValue.setInt(hostUid); // map of host uid to their position in the original vector map<int, vector<int>> hostPosition; vector<bool> toRemove = vector<bool>(data.size(), false); for (size_t i = 0; i < data.size(); i++) { vector<FieldValue>* valueList = data[i]->getMutableValues(); int uid; if (uidField > 0 && (int)data[i]->getValues().size() >= uidField && (data[i]->getValues())[uidField - 1].mValue.getType() == INT) { uid = (*data[i]->getMutableValues())[uidField - 1].mValue.int_value; } else { ALOGE("Malformed log, uid not found. %s", data[i]->ToString().c_str()); continue; } const int hostUid = uidMap->getHostUidOrSelf(uid); if (hostUid != uid) { (*valueList)[0].mValue.setInt(hostUid); } if (hostPosition.find(hostUid) == hostPosition.end()) { hostPosition[hostUid].push_back(i); } else { auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId); if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) { int uidField = it->second; // uidField is the field number in proto, // starting from 1 if (uidField > 0 && (int)event->getValues().size() >= uidField && (event->getValues())[uidField - 1].mValue.getType() == INT) { Value& value = (*event->getMutableValues())[uidField - 1].mValue; const int hostUid = uidMap->getHostUidOrSelf(value.int_value); value.setInt(hostUid); if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) { toRemove[i] = true; } else { ALOGE("Malformed log, uid not found. %s", event->ToString().c_str()); return; } hostPosition[hostUid].push_back(i); } } } // 2. sort the data, bit-wise sort(data.begin(), data.end(), [](const shared_ptr<LogEvent>& lhs, const shared_ptr<LogEvent>& rhs) { if (lhs->size() != rhs->size()) { return lhs->size() < rhs->size(); } const std::vector<FieldValue>& lhsValues = lhs->getValues(); const std::vector<FieldValue>& rhsValues = rhs->getValues(); for (int i = 0; i < (int)lhs->size(); i++) { if (lhsValues[i] != rhsValues[i]) { return lhsValues[i] < rhsValues[i]; } } return false; }); vector<shared_ptr<LogEvent>> mergedData; const vector<int>& additiveFieldsVec = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields; const set<int> additiveFields(additiveFieldsVec.begin(), additiveFieldsVec.end()); bool needMerge = true; // 3. do the merge. // The loop invariant is this: for every event, check if it differs on // non-additive fields, or have different attribution chain length. // If so, no need to merge, add itself to the result. // Otherwise, merge the value onto the one immediately next to it. for (int i = 0; i < (int)data.size() - 1; i++) { // Size different, must be different chains. if (data[i]->size() != data[i + 1]->size()) { for (size_t i = 0; i < toRemove.size(); i++) { if (!toRemove[i]) { mergedData.push_back(data[i]); continue; } vector<FieldValue>* lhsValues = data[i]->getMutableValues(); vector<FieldValue>* rhsValues = data[i + 1]->getMutableValues(); needMerge = true; for (int p = 0; p < (int)lhsValues->size(); p++) { if ((*lhsValues)[p] != (*rhsValues)[p]) { int pos = (*lhsValues)[p].mField.getPosAtDepth(0); // Differ on non-additive field, abort. if (additiveFields.find(pos) == additiveFields.end()) { needMerge = false; break; } } } if (!needMerge) { mergedData.push_back(data[i]); continue; } // This should be infrequent operation. for (int p = 0; p < (int)lhsValues->size(); p++) { int pos = (*lhsValues)[p].mField.getPosAtDepth(0); if (additiveFields.find(pos) != additiveFields.end()) { (*rhsValues)[p].mValue += (*lhsValues)[p].mValue; } } } mergedData.push_back(data.back()); data.clear(); data = mergedData; } Loading