Revert "Revert "support work chain in pulled atoms""
This reverts commit 9c7b131996.
Reason for revert: Fixed build failures due to merge
Change-Id: I7d7bfed3a3234b966f3fe3fd6e0cbc63d2bedf83
Test: unit test
This commit is contained in:
@@ -59,7 +59,7 @@ bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* da
|
||||
}
|
||||
data->clear();
|
||||
for (const StatsLogEventWrapper& it : returned_value) {
|
||||
data->push_back(make_shared<LogEvent>(it));
|
||||
LogEvent::createLogEvents(it, *data);
|
||||
}
|
||||
VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
|
||||
return true;
|
||||
|
||||
7
cmds/statsd/src/external/StatsPuller.cpp
vendored
7
cmds/statsd/src/external/StatsPuller.cpp
vendored
@@ -32,9 +32,10 @@ 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);
|
||||
}
|
||||
@@ -64,8 +65,8 @@ bool StatsPuller::Pull(const int64_t elapsedTimeNs, std::vector<std::shared_ptr<
|
||||
data->setLogdWallClockTimestampNs(wallClockTimeNs);
|
||||
}
|
||||
if (ret && mCachedData.size() > 0) {
|
||||
mergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
|
||||
(*data) = mCachedData;
|
||||
mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
|
||||
(*data) = mCachedData;
|
||||
}
|
||||
StatsdStats::getInstance().notePullDelay(mTagId, getElapsedRealtimeNs() - elapsedTimeNs);
|
||||
return ret;
|
||||
|
||||
99
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
99
cmds/statsd/src/external/StatsPullerManager.cpp
vendored
@@ -54,52 +54,42 @@ 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},
|
||||
{2},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
|
||||
{{3}, 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
|
||||
@@ -107,169 +97,140 @@ 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},
|
||||
{2},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
|
||||
{{3}, 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_voltage
|
||||
{{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
|
||||
// battery_level
|
||||
{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},
|
||||
{},
|
||||
{{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 */, {} /* non additive fields */,
|
||||
5 * NS_PER_SEC /* min cool-down in seconds*/,
|
||||
new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
|
||||
{{} /* 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.
|
||||
{android::util::BUILD_INFORMATION,
|
||||
{{}, {},
|
||||
1 * NS_PER_SEC,
|
||||
new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}},
|
||||
{{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}},
|
||||
};
|
||||
|
||||
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
|
||||
|
||||
@@ -36,9 +36,6 @@ 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;
|
||||
|
||||
196
cmds/statsd/src/external/puller_util.cpp
vendored
196
cmds/statsd/src/external/puller_util.cpp
vendored
@@ -25,67 +25,13 @@ 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:
|
||||
@@ -95,7 +41,7 @@ bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<in
|
||||
* int byte_send = 3;
|
||||
* int byte_recv = 4;
|
||||
* }
|
||||
* additive fields are {3, 4}, non-additive field is {2}
|
||||
* additive fields are {3, 4}
|
||||
* 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]
|
||||
@@ -104,65 +50,119 @@ bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<in
|
||||
* 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 mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
|
||||
int tagId) {
|
||||
void mapAndMergeIsolatedUidsToHostUid(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;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) {
|
||||
toRemove[i] = true;
|
||||
} else {
|
||||
hostPosition[hostUid].push_back(i);
|
||||
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);
|
||||
} else {
|
||||
ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
for (size_t i = 0; i < toRemove.size(); i++) {
|
||||
if (!toRemove[i]) {
|
||||
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()) {
|
||||
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;
|
||||
}
|
||||
|
||||
4
cmds/statsd/src/external/puller_util.h
vendored
4
cmds/statsd/src/external/puller_util.h
vendored
@@ -25,8 +25,8 @@ namespace android {
|
||||
namespace os {
|
||||
namespace statsd {
|
||||
|
||||
void mergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
|
||||
const sp<UidMap>& uidMap, int tagId);
|
||||
void mapAndMergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
|
||||
const sp<UidMap>& uidMap, int tagId);
|
||||
|
||||
} // namespace statsd
|
||||
} // namespace os
|
||||
|
||||
@@ -41,13 +41,28 @@ LogEvent::LogEvent(log_msg& msg) {
|
||||
}
|
||||
}
|
||||
|
||||
LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper) {
|
||||
LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex) {
|
||||
mTagId = statsLogEventWrapper.getTagId();
|
||||
mLogdTimestampNs = statsLogEventWrapper.getWallClockTimeNs();
|
||||
mElapsedTimestampNs = statsLogEventWrapper.getElapsedRealTimeNs();
|
||||
mLogUid = 0;
|
||||
int workChainPosOffset = 0;
|
||||
if (workChainIndex != -1) {
|
||||
const WorkChain& wc = statsLogEventWrapper.getWorkChains()[workChainIndex];
|
||||
// chains are at field 1, level 2
|
||||
int depth = 2;
|
||||
for (int i = 0; i < (int)wc.uids.size(); i++) {
|
||||
int pos[] = {1, i + 1, 1};
|
||||
mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.uids[i])));
|
||||
pos[2]++;
|
||||
mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.tags[i])));
|
||||
mValues.back().mField.decorateLastPos(2);
|
||||
}
|
||||
mValues.back().mField.decorateLastPos(1);
|
||||
workChainPosOffset = 1;
|
||||
}
|
||||
for (int i = 0; i < (int)statsLogEventWrapper.getElements().size(); i++) {
|
||||
Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1));
|
||||
Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1 + workChainPosOffset));
|
||||
switch (statsLogEventWrapper.getElements()[i].type) {
|
||||
case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::INT:
|
||||
mValues.push_back(
|
||||
@@ -79,6 +94,17 @@ LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper) {
|
||||
}
|
||||
}
|
||||
|
||||
void LogEvent::createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
|
||||
std::vector<std::shared_ptr<LogEvent>>& logEvents) {
|
||||
if (statsLogEventWrapper.getWorkChains().size() == 0) {
|
||||
logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, -1));
|
||||
} else {
|
||||
for (size_t i = 0; i < statsLogEventWrapper.getWorkChains().size(); i++) {
|
||||
logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
|
||||
mLogdTimestampNs = wallClockTimestampNs;
|
||||
mTagId = tagId;
|
||||
|
||||
@@ -65,7 +65,16 @@ public:
|
||||
*/
|
||||
explicit LogEvent(log_msg& msg);
|
||||
|
||||
explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper);
|
||||
/**
|
||||
* Creates LogEvent from StatsLogEventWrapper.
|
||||
*/
|
||||
static void createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
|
||||
std::vector<std::shared_ptr<LogEvent>>& logEvents);
|
||||
|
||||
/**
|
||||
* Construct one LogEvent from a StatsLogEventWrapper with the i-th work chain. -1 if no chain.
|
||||
*/
|
||||
explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex);
|
||||
|
||||
/**
|
||||
* Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
|
||||
|
||||
@@ -165,7 +165,7 @@ private:
|
||||
const bool mSkipZeroDiffOutput;
|
||||
|
||||
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
|
||||
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
|
||||
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
|
||||
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
|
||||
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset);
|
||||
FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
|
||||
|
||||
@@ -454,6 +454,16 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
|
||||
ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
|
||||
return false;
|
||||
}
|
||||
if (!metric.has_value_field()) {
|
||||
ALOGW("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
|
||||
return false;
|
||||
}
|
||||
std::vector<Matcher> fieldMatchers;
|
||||
translateFieldMatcher(metric.value_field(), &fieldMatchers);
|
||||
if (fieldMatchers.size() < 1) {
|
||||
ALOGW("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
|
||||
return false;
|
||||
}
|
||||
|
||||
int metricIndex = allMetricProducers.size();
|
||||
metricMap.insert({metric.id(), metricIndex});
|
||||
|
||||
@@ -394,6 +394,167 @@ TEST(LogEventTest, TestKeyValuePairsEvent) {
|
||||
EXPECT_EQ(1.1f, item16.mValue.float_value);
|
||||
}
|
||||
|
||||
TEST(LogEventTest, TestStatsLogEventWrapperNoChain) {
|
||||
Parcel parcel;
|
||||
// tag id
|
||||
parcel.writeInt32(1);
|
||||
// elapsed realtime
|
||||
parcel.writeInt64(1111L);
|
||||
// wallclock time
|
||||
parcel.writeInt64(2222L);
|
||||
// no chain
|
||||
parcel.writeInt32(0);
|
||||
// 2 data
|
||||
parcel.writeInt32(2);
|
||||
// int 6
|
||||
parcel.writeInt32(1);
|
||||
parcel.writeInt32(6);
|
||||
// long 10
|
||||
parcel.writeInt32(2);
|
||||
parcel.writeInt64(10);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
StatsLogEventWrapper statsLogEventWrapper;
|
||||
EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
|
||||
EXPECT_EQ(1, statsLogEventWrapper.getTagId());
|
||||
EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
|
||||
EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
|
||||
EXPECT_EQ(0, statsLogEventWrapper.getWorkChains().size());
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
|
||||
EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
|
||||
EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
|
||||
LogEvent event(statsLogEventWrapper, -1);
|
||||
EXPECT_EQ(1, event.GetTagId());
|
||||
EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
|
||||
EXPECT_EQ(2222L, event.GetLogdTimestampNs());
|
||||
EXPECT_EQ(2, event.size());
|
||||
EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
|
||||
EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
|
||||
}
|
||||
|
||||
TEST(LogEventTest, TestStatsLogEventWrapperWithChain) {
|
||||
Parcel parcel;
|
||||
// tag id
|
||||
parcel.writeInt32(1);
|
||||
// elapsed realtime
|
||||
parcel.writeInt64(1111L);
|
||||
// wallclock time
|
||||
parcel.writeInt64(2222L);
|
||||
// 3 chains
|
||||
parcel.writeInt32(3);
|
||||
// chain1, 2 nodes (1, "tag1") (2, "tag2")
|
||||
parcel.writeInt32(2);
|
||||
parcel.writeInt32(1);
|
||||
parcel.writeString16(String16("tag1"));
|
||||
parcel.writeInt32(2);
|
||||
parcel.writeString16(String16("tag2"));
|
||||
// chain2, 1 node (3, "tag3")
|
||||
parcel.writeInt32(1);
|
||||
parcel.writeInt32(3);
|
||||
parcel.writeString16(String16("tag3"));
|
||||
// chain3, 2 nodes (4, "") (5, "")
|
||||
parcel.writeInt32(2);
|
||||
parcel.writeInt32(4);
|
||||
parcel.writeString16(String16(""));
|
||||
parcel.writeInt32(5);
|
||||
parcel.writeString16(String16(""));
|
||||
// 2 data
|
||||
parcel.writeInt32(2);
|
||||
// int 6
|
||||
parcel.writeInt32(1);
|
||||
parcel.writeInt32(6);
|
||||
// long 10
|
||||
parcel.writeInt32(2);
|
||||
parcel.writeInt64(10);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
StatsLogEventWrapper statsLogEventWrapper;
|
||||
EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
|
||||
EXPECT_EQ(1, statsLogEventWrapper.getTagId());
|
||||
EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
|
||||
EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
|
||||
EXPECT_EQ(3, statsLogEventWrapper.getWorkChains().size());
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids.size());
|
||||
EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[0].uids[0]);
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids[1]);
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].tags.size());
|
||||
EXPECT_EQ("tag1", statsLogEventWrapper.getWorkChains()[0].tags[0]);
|
||||
EXPECT_EQ("tag2", statsLogEventWrapper.getWorkChains()[0].tags[1]);
|
||||
EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].uids.size());
|
||||
EXPECT_EQ(3, statsLogEventWrapper.getWorkChains()[1].uids[0]);
|
||||
EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].tags.size());
|
||||
EXPECT_EQ("tag3", statsLogEventWrapper.getWorkChains()[1].tags[0]);
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
|
||||
EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
|
||||
EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].uids.size());
|
||||
EXPECT_EQ(4, statsLogEventWrapper.getWorkChains()[2].uids[0]);
|
||||
EXPECT_EQ(5, statsLogEventWrapper.getWorkChains()[2].uids[1]);
|
||||
EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].tags.size());
|
||||
EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[0]);
|
||||
EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[1]);
|
||||
|
||||
LogEvent event(statsLogEventWrapper, -1);
|
||||
EXPECT_EQ(1, event.GetTagId());
|
||||
EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
|
||||
EXPECT_EQ(2222L, event.GetLogdTimestampNs());
|
||||
EXPECT_EQ(2, event.size());
|
||||
EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
|
||||
EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
|
||||
|
||||
LogEvent event1(statsLogEventWrapper, 0);
|
||||
|
||||
EXPECT_EQ(1, event1.GetTagId());
|
||||
EXPECT_EQ(1111L, event1.GetElapsedTimestampNs());
|
||||
EXPECT_EQ(2222L, event1.GetLogdTimestampNs());
|
||||
EXPECT_EQ(6, event1.size());
|
||||
EXPECT_EQ(1, event1.getValues()[0].mValue.int_value);
|
||||
EXPECT_EQ(0x2010101, event1.getValues()[0].mField.getField());
|
||||
EXPECT_EQ("tag1", event1.getValues()[1].mValue.str_value);
|
||||
EXPECT_EQ(0x2010182, event1.getValues()[1].mField.getField());
|
||||
EXPECT_EQ(2, event1.getValues()[2].mValue.int_value);
|
||||
EXPECT_EQ(0x2010201, event1.getValues()[2].mField.getField());
|
||||
EXPECT_EQ("tag2", event1.getValues()[3].mValue.str_value);
|
||||
EXPECT_EQ(0x2018282, event1.getValues()[3].mField.getField());
|
||||
EXPECT_EQ(6, event1.getValues()[4].mValue.int_value);
|
||||
EXPECT_EQ(0x20000, event1.getValues()[4].mField.getField());
|
||||
EXPECT_EQ(10, event1.getValues()[5].mValue.long_value);
|
||||
EXPECT_EQ(0x30000, event1.getValues()[5].mField.getField());
|
||||
|
||||
LogEvent event2(statsLogEventWrapper, 1);
|
||||
|
||||
EXPECT_EQ(1, event2.GetTagId());
|
||||
EXPECT_EQ(1111L, event2.GetElapsedTimestampNs());
|
||||
EXPECT_EQ(2222L, event2.GetLogdTimestampNs());
|
||||
EXPECT_EQ(4, event2.size());
|
||||
EXPECT_EQ(3, event2.getValues()[0].mValue.int_value);
|
||||
EXPECT_EQ(0x2010101, event2.getValues()[0].mField.getField());
|
||||
EXPECT_EQ("tag3", event2.getValues()[1].mValue.str_value);
|
||||
EXPECT_EQ(0x2018182, event2.getValues()[1].mField.getField());
|
||||
EXPECT_EQ(6, event2.getValues()[2].mValue.int_value);
|
||||
EXPECT_EQ(0x20000, event2.getValues()[2].mField.getField());
|
||||
EXPECT_EQ(10, event2.getValues()[3].mValue.long_value);
|
||||
EXPECT_EQ(0x30000, event2.getValues()[3].mField.getField());
|
||||
|
||||
LogEvent event3(statsLogEventWrapper, 2);
|
||||
|
||||
EXPECT_EQ(1, event3.GetTagId());
|
||||
EXPECT_EQ(1111L, event3.GetElapsedTimestampNs());
|
||||
EXPECT_EQ(2222L, event3.GetLogdTimestampNs());
|
||||
EXPECT_EQ(6, event3.size());
|
||||
EXPECT_EQ(4, event3.getValues()[0].mValue.int_value);
|
||||
EXPECT_EQ(0x2010101, event3.getValues()[0].mField.getField());
|
||||
EXPECT_EQ("", event3.getValues()[1].mValue.str_value);
|
||||
EXPECT_EQ(0x2010182, event3.getValues()[1].mField.getField());
|
||||
EXPECT_EQ(5, event3.getValues()[2].mValue.int_value);
|
||||
EXPECT_EQ(0x2010201, event3.getValues()[2].mField.getField());
|
||||
EXPECT_EQ("", event3.getValues()[3].mValue.str_value);
|
||||
EXPECT_EQ(0x2018282, event3.getValues()[3].mField.getField());
|
||||
EXPECT_EQ(6, event3.getValues()[4].mValue.int_value);
|
||||
EXPECT_EQ(0x20000, event3.getValues()[4].mField.getField());
|
||||
EXPECT_EQ(10, event3.getValues()[5].mValue.long_value);
|
||||
EXPECT_EQ(0x30000, event3.getValues()[5].mField.getField());
|
||||
}
|
||||
|
||||
TEST(LogEventTest, TestBinaryFieldAtom) {
|
||||
Atom launcherAtom;
|
||||
|
||||
12
cmds/statsd/tests/external/puller_util_test.cpp
vendored
12
cmds/statsd/tests/external/puller_util_test.cpp
vendored
@@ -80,7 +80,7 @@ TEST(puller_util, MergeNoDimension) {
|
||||
.WillRepeatedly(Return(hostUid));
|
||||
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
|
||||
.WillRepeatedly(ReturnArg<0>());
|
||||
mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
|
||||
vector<vector<int>> actual;
|
||||
extractIntoVector(inputData, actual);
|
||||
@@ -120,7 +120,7 @@ TEST(puller_util, MergeWithDimension) {
|
||||
.WillRepeatedly(Return(hostUid));
|
||||
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
|
||||
.WillRepeatedly(ReturnArg<0>());
|
||||
mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
|
||||
vector<vector<int>> actual;
|
||||
extractIntoVector(inputData, actual);
|
||||
@@ -154,7 +154,7 @@ TEST(puller_util, NoMergeHostUidOnly) {
|
||||
.WillRepeatedly(Return(hostUid));
|
||||
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
|
||||
.WillRepeatedly(ReturnArg<0>());
|
||||
mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
|
||||
// 20->32->31
|
||||
// 20->22->21
|
||||
@@ -190,7 +190,7 @@ TEST(puller_util, IsolatedUidOnly) {
|
||||
.WillRepeatedly(Return(hostUid));
|
||||
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
|
||||
.WillRepeatedly(ReturnArg<0>());
|
||||
mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
|
||||
// 20->32->31
|
||||
// 20->22->21
|
||||
@@ -231,7 +231,7 @@ TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
|
||||
|
||||
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
|
||||
EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
|
||||
mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
|
||||
|
||||
vector<vector<int>> actual;
|
||||
extractIntoVector(inputData, actual);
|
||||
@@ -256,7 +256,7 @@ TEST(puller_util, NoNeedToMerge) {
|
||||
inputData.push_back(event);
|
||||
|
||||
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
|
||||
mergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
|
||||
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
|
||||
|
||||
EXPECT_EQ(2, (int)inputData.size());
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public final class StatsLogEventWrapper implements Parcelable {
|
||||
int mTag;
|
||||
long mElapsedTimeNs;
|
||||
long mWallClockTimeNs;
|
||||
WorkSource mWorkSource = null;
|
||||
|
||||
public StatsLogEventWrapper(int tag, long elapsedTimeNs, long wallClockTimeNs) {
|
||||
this.mTag = tag;
|
||||
@@ -70,6 +71,17 @@ public final class StatsLogEventWrapper implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set work source if any.
|
||||
*/
|
||||
public void setWorkSource(WorkSource ws) {
|
||||
if (ws.getWorkChains() == null || ws.getWorkChains().size() == 0) {
|
||||
Slog.w(TAG, "Empty worksource!");
|
||||
return;
|
||||
}
|
||||
mWorkSource = ws;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a int value.
|
||||
*/
|
||||
@@ -119,11 +131,6 @@ public final class StatsLogEventWrapper implements Parcelable {
|
||||
mValues.add(val ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the stored fields to a byte array. Will first write a new-line character to denote
|
||||
* END_LIST before writing contents to byte array.
|
||||
*/
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
@@ -133,6 +140,34 @@ public final class StatsLogEventWrapper implements Parcelable {
|
||||
out.writeInt(mTag);
|
||||
out.writeLong(mElapsedTimeNs);
|
||||
out.writeLong(mWallClockTimeNs);
|
||||
if (mWorkSource != null) {
|
||||
ArrayList<android.os.WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
|
||||
// number of chains
|
||||
out.writeInt(workChains.size());
|
||||
for (int i = 0; i < workChains.size(); i++) {
|
||||
android.os.WorkSource.WorkChain wc = workChains.get(i);
|
||||
if (wc.getSize() == 0) {
|
||||
Slog.w(TAG, "Empty work chain.");
|
||||
out.writeInt(0);
|
||||
continue;
|
||||
}
|
||||
if (wc.getUids().length != wc.getTags().length
|
||||
|| wc.getUids().length != wc.getSize()) {
|
||||
Slog.w(TAG, "Malformated work chain.");
|
||||
out.writeInt(0);
|
||||
continue;
|
||||
}
|
||||
// number of nodes
|
||||
out.writeInt(wc.getSize());
|
||||
for (int j = 0; j < wc.getSize(); j++) {
|
||||
out.writeInt(wc.getUids()[j]);
|
||||
out.writeString(wc.getTags()[j] == null ? "" : wc.getTags()[j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no chains
|
||||
out.writeInt(0);
|
||||
}
|
||||
out.writeInt(mTypes.size());
|
||||
for (int i = 0; i < mTypes.size(); i++) {
|
||||
out.writeInt(mTypes.get(i));
|
||||
|
||||
@@ -82,6 +82,11 @@ struct StatsLogValue {
|
||||
STATS_LOG_VALUE_TYPE type;
|
||||
};
|
||||
|
||||
struct WorkChain {
|
||||
std::vector<int32_t> uids;
|
||||
std::vector<std::string> tags;
|
||||
};
|
||||
|
||||
// Represents a parcelable object. Only used to send data from Android OS to statsd.
|
||||
class StatsLogEventWrapper : public android::Parcelable {
|
||||
public:
|
||||
@@ -99,7 +104,9 @@ class StatsLogEventWrapper : public android::Parcelable {
|
||||
|
||||
int64_t getWallClockTimeNs() const { return mWallClockTimeNs; }
|
||||
|
||||
std::vector<StatsLogValue> getElements() const { return mElements; }
|
||||
const std::vector<StatsLogValue>& getElements() const { return mElements; }
|
||||
|
||||
const std::vector<WorkChain>& getWorkChains() const { return mWorkChains; }
|
||||
|
||||
private:
|
||||
int mTagId;
|
||||
@@ -109,6 +116,8 @@ class StatsLogEventWrapper : public android::Parcelable {
|
||||
int64_t mWallClockTimeNs;
|
||||
|
||||
std::vector<StatsLogValue> mElements;
|
||||
|
||||
std::vector<WorkChain> mWorkChains;
|
||||
};
|
||||
} // Namespace os
|
||||
} // Namespace android
|
||||
|
||||
@@ -58,6 +58,31 @@ status_t StatsLogEventWrapper::readFromParcel(const Parcel* in) {
|
||||
ALOGE("statsd could not read wall clock time from parcel");
|
||||
return res;
|
||||
}
|
||||
int numWorkChain = 0;
|
||||
if ((res = in->readInt32(&numWorkChain)) != OK) {
|
||||
ALOGE("statsd could not read number of work chains from parcel");
|
||||
return res;
|
||||
}
|
||||
if (numWorkChain > 0) {
|
||||
for (int i = 0; i < numWorkChain; i++) {
|
||||
int numNodes = 0;
|
||||
if ((res = in->readInt32(&numNodes)) != OK) {
|
||||
ALOGE(
|
||||
"statsd could not read number of nodes in work chain from parcel");
|
||||
return res;
|
||||
}
|
||||
if (numNodes == 0) {
|
||||
ALOGE("empty work chain");
|
||||
return BAD_VALUE;
|
||||
}
|
||||
WorkChain wc;
|
||||
for (int j = 0; j < numNodes; j++) {
|
||||
wc.uids.push_back(in->readInt32());
|
||||
wc.tags.push_back(std::string(String8(in->readString16()).string()));
|
||||
}
|
||||
mWorkChains.push_back(wc);
|
||||
}
|
||||
}
|
||||
int dataSize = 0;
|
||||
if ((res = in->readInt32(&dataSize)) != OK) {
|
||||
ALOGE("statsd could not read data size from parcel");
|
||||
|
||||
Reference in New Issue
Block a user