Mediametrics: Add max/min volume and duration in AudioPowerUsageData
Bug: 201353537
Test: adb shell dumpsys media.metrics --all | egrep -A10 PowerUsage
Change-Id: I3c603cb03c3b7f84f2572ac43c2da2dc0c798553
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
index 7fb69be..30d69ab 100644
--- a/services/audioflinger/TrackMetrics.h
+++ b/services/audioflinger/TrackMetrics.h
@@ -116,6 +116,21 @@
mDeviceStartupMs.add(startupMs);
}
+ void updateMinMaxVolume(int64_t durationNs, double deviceVolume) {
+ if (deviceVolume > mMaxVolume) {
+ mMaxVolume = deviceVolume;
+ mMaxVolumeDurationNs = durationNs;
+ } else if (deviceVolume == mMaxVolume) {
+ mMaxVolumeDurationNs += durationNs;
+ }
+ if (deviceVolume < mMinVolume) {
+ mMinVolume = deviceVolume;
+ mMinVolumeDurationNs = durationNs;
+ } else if (deviceVolume == mMinVolume) {
+ mMinVolumeDurationNs += durationNs;
+ }
+ }
+
// may be called multiple times during an interval
void logVolume(float volume) {
const int64_t timeNs = systemTime();
@@ -123,10 +138,13 @@
if (mStartVolumeTimeNs == 0) {
mDeviceVolume = mVolume = volume;
mLastVolumeChangeTimeNs = mStartVolumeTimeNs = timeNs;
+ updateMinMaxVolume(0, mVolume);
return;
}
+ const int64_t durationNs = timeNs - mLastVolumeChangeTimeNs;
+ updateMinMaxVolume(durationNs, mVolume);
mDeviceVolume = (mDeviceVolume * (mLastVolumeChangeTimeNs - mStartVolumeTimeNs) +
- mVolume * (timeNs - mLastVolumeChangeTimeNs)) / (timeNs - mStartVolumeTimeNs);
+ mVolume * durationNs) / (timeNs - mStartVolumeTimeNs);
mVolume = volume;
mLastVolumeChangeTimeNs = timeNs;
}
@@ -157,7 +175,11 @@
.set(AMEDIAMETRICS_PROP_EVENT, eventName)
.set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
if (mIsOut) {
- item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume);
+ item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume)
+ .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, mMaxVolumeDurationNs)
+ .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, mMaxVolume)
+ .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, mMinVolumeDurationNs)
+ .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, mMinVolume);
}
if (mDeviceLatencyMs.getN() > 0) {
item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean())
@@ -185,6 +207,10 @@
mDeviceVolume = 0.f;
mStartVolumeTimeNs = 0;
mLastVolumeChangeTimeNs = 0;
+ mMinVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ mMaxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ mMinVolumeDurationNs = 0;
+ mMaxVolumeDurationNs = 0;
mDeviceLatencyMs.reset();
mDeviceStartupMs.reset();
@@ -214,6 +240,12 @@
int64_t mStartVolumeTimeNs GUARDED_BY(mLock) = 0;
int64_t mLastVolumeChangeTimeNs GUARDED_BY(mLock) = 0;
+ // Min/Max volume
+ double mMinVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ double mMaxVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ int64_t mMinVolumeDurationNs GUARDED_BY(mLock) = 0;
+ int64_t mMaxVolumeDurationNs GUARDED_BY(mLock) = 0;
+
// latency and startup for each interval.
audio_utils::Statistics<double> mDeviceLatencyMs GUARDED_BY(mLock);
audio_utils::Statistics<double> mDeviceStartupMs GUARDED_BY(mLock);
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index ab74c8e..5787e9e 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -45,6 +45,10 @@
#define AUDIO_POWER_USAGE_PROP_DURATION_NS "durationNs" // int64
#define AUDIO_POWER_USAGE_PROP_TYPE "type" // int32
#define AUDIO_POWER_USAGE_PROP_VOLUME "volume" // double
+#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS "minVolumeDurationNs" // int64
+#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME "minVolume" // double
+#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS "maxVolumeDurationNs" // int64
+#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME "maxVolume" // double
namespace android::mediametrics {
@@ -141,13 +145,34 @@
double volume;
if (!item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &volume)) return;
+ int64_t min_volume_duration_ns;
+ if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, &min_volume_duration_ns)) {
+ return;
+ }
+
+ double min_volume;
+ if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &min_volume)) return;
+
+ int64_t max_volume_duration_ns;
+ if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, &max_volume_duration_ns)) {
+ return;
+ }
+
+ double max_volume;
+ if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &max_volume)) return;
+
const int32_t duration_secs = (int32_t)(duration_ns / NANOS_PER_SECOND);
- const float average_volume = (float)volume;
+ const int32_t min_volume_duration_secs = (int32_t)(min_volume_duration_ns / NANOS_PER_SECOND);
+ const int32_t max_volume_duration_secs = (int32_t)(max_volume_duration_ns / NANOS_PER_SECOND);
const int result = android::util::stats_write(android::util::AUDIO_POWER_USAGE_DATA_REPORTED,
audio_device,
duration_secs,
- average_volume,
- type);
+ (float)volume,
+ type,
+ min_volume_duration_secs,
+ (float)min_volume,
+ max_volume_duration_secs,
+ (float)max_volume);
std::stringstream log;
log << "result:" << result << " {"
@@ -155,17 +180,43 @@
<< android::util::AUDIO_POWER_USAGE_DATA_REPORTED
<< " audio_device:" << audio_device
<< " duration_secs:" << duration_secs
- << " average_volume:" << average_volume
+ << " average_volume:" << (float)volume
<< " type:" << type
+ << " min_volume_duration_secs:" << min_volume_duration_secs
+ << " min_volume:" << (float)min_volume
+ << " max_volume_duration_secs:" << max_volume_duration_secs
+ << " max_volume:" << (float)max_volume
<< " }";
mStatsdLog->log(android::util::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
}
+void AudioPowerUsage::updateMinMaxVolumeAndDuration(
+ const int64_t cur_max_volume_duration_ns, const double cur_max_volume,
+ const int64_t cur_min_volume_duration_ns, const double cur_min_volume,
+ int64_t& f_max_volume_duration_ns, double& f_max_volume,
+ int64_t& f_min_volume_duration_ns, double& f_min_volume)
+{
+ if (f_min_volume > cur_min_volume) {
+ f_min_volume = cur_min_volume;
+ f_min_volume_duration_ns = cur_min_volume_duration_ns;
+ } else if (f_min_volume == cur_min_volume) {
+ f_min_volume_duration_ns += cur_min_volume_duration_ns;
+ }
+ if (f_max_volume < cur_max_volume) {
+ f_max_volume = cur_max_volume;
+ f_max_volume_duration_ns = cur_max_volume_duration_ns;
+ } else if (f_max_volume == cur_max_volume) {
+ f_max_volume_duration_ns += cur_max_volume_duration_ns;
+ }
+}
+
bool AudioPowerUsage::saveAsItem_l(
- int32_t device, int64_t duration_ns, int32_t type, double average_vol)
+ int32_t device, int64_t duration_ns, int32_t type, double average_vol,
+ int64_t max_volume_duration_ns, double max_volume,
+ int64_t min_volume_duration_ns, double min_volume)
{
ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
- (long long)duration_ns, average_vol );
+ (long long)duration_ns, average_vol);
if (duration_ns == 0) {
return true; // skip duration 0 usage
}
@@ -193,10 +244,36 @@
item->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, final_volume);
item->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
- ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f)", __func__,
+ // Update the max/min volume and duration
+ int64_t final_min_volume_duration_ns;
+ int64_t final_max_volume_duration_ns;
+ double final_min_volume;
+ double final_max_volume;
+
+ item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
+ &final_min_volume_duration_ns);
+ item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &final_min_volume);
+ item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
+ &final_max_volume_duration_ns);
+ item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &final_max_volume);
+ updateMinMaxVolumeAndDuration(max_volume_duration_ns, max_volume,
+ min_volume_duration_ns, min_volume,
+ final_max_volume_duration_ns, final_max_volume,
+ final_min_volume_duration_ns, final_min_volume);
+ item->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
+ final_min_volume_duration_ns);
+ item->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, final_min_volume);
+ item->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
+ final_max_volume_duration_ns);
+ item->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, final_max_volume);
+
+ ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f) min(%lld, %f) max(%lld, %f)",
+ __func__,
device, type,
(long long)item_duration_ns, item_volume,
- (long long)final_duration_ns, final_volume);
+ (long long)final_duration_ns, final_volume,
+ (long long)final_min_volume_duration_ns, final_min_volume,
+ (long long)final_max_volume_duration_ns, final_max_volume);
return true;
}
@@ -208,12 +285,18 @@
sitem->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, duration_ns);
sitem->setInt32(AUDIO_POWER_USAGE_PROP_TYPE, type);
sitem->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, average_vol);
+ sitem->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, min_volume_duration_ns);
+ sitem->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, min_volume);
+ sitem->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, max_volume_duration_ns);
+ sitem->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, max_volume);
mItems.emplace_back(sitem);
return true;
}
bool AudioPowerUsage::saveAsItems_l(
- int32_t device, int64_t duration_ns, int32_t type, double average_vol)
+ int32_t device, int64_t duration_ns, int32_t type, double average_vol,
+ int64_t max_volume_duration, double max_volume,
+ int64_t min_volume_duration, double min_volume)
{
ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
(long long)duration_ns, average_vol );
@@ -232,7 +315,9 @@
int32_t tmp_device = device_bits & -device_bits; // get lowest bit
device_bits ^= tmp_device; // clear lowest bit
tmp_device |= input_bit; // restore input bit
- ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol);
+ ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol,
+ max_volume_duration, max_volume,
+ min_volume_duration, min_volume);
ALOGV("%s: device %#x recorded, remaining device_bits = %#x", __func__,
tmp_device, device_bits);
@@ -250,9 +335,28 @@
return;
}
double deviceVolume = 1.;
- if (isTrack && !item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
- return;
+ int64_t maxVolumeDurationNs = 0;
+ double maxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ int64_t minVolumeDurationNs = 0;
+ double minVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ if (isTrack) {
+ if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
+ return;
+ }
+ if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, &maxVolumeDurationNs)) {
+ return;
+ }
+ if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, &maxVolume)) {
+ return;
+ }
+ if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, &minVolumeDurationNs)) {
+ return;
+ }
+ if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, &minVolume)) {
+ return;
+ }
}
+
int32_t type = 0;
std::string type_string;
if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
@@ -285,7 +389,8 @@
ALOGV("device = %s => %d", device_strings.c_str(), device);
}
std::lock_guard l(mLock);
- saveAsItems_l(device, deviceTimeNs, type, deviceVolume);
+ saveAsItems_l(device, deviceTimeNs, type, deviceVolume,
+ maxVolumeDurationNs, maxVolume, minVolumeDurationNs, minVolume);
}
void AudioPowerUsage::checkMode(const std::shared_ptr<const mediametrics::Item>& item)
@@ -299,10 +404,17 @@
if (mMode == "AUDIO_MODE_IN_CALL") { // leaving call mode
const int64_t endCallNs = item->getTimestamp();
const int64_t durationNs = endCallNs - mDeviceTimeNs;
+ const int64_t volumeDurationNs = endCallNs - mVolumeTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(endCallNs - mVolumeTimeNs)) / (double)durationNs;
- saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+ mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
+ updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
+ volumeDurationNs, mVoiceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
+ saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
}
} else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
mStartCallNs = item->getTimestamp(); // advisory only
@@ -327,10 +439,15 @@
if (mMode == "AUDIO_MODE_IN_CALL") {
const int64_t timeNs = item->getTimestamp();
const int64_t durationNs = timeNs - mDeviceTimeNs;
+ const int64_t volumeDurationNs = timeNs - mVolumeTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(timeNs - mVolumeTimeNs)) / (double)durationNs;
+ mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
mVolumeTimeNs = timeNs;
+ updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
+ volumeDurationNs, mVoiceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
}
}
ALOGV("%s: new voice volume:%lf old voice volume:%lf", __func__, voiceVolume, mVoiceVolume);
@@ -358,15 +475,26 @@
// Save statistics
const int64_t endDeviceNs = item->getTimestamp();
const int64_t durationNs = endDeviceNs - mDeviceTimeNs;
+ const int64_t volumeDurationNs = endDeviceNs - mVolumeTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(endDeviceNs - mVolumeTimeNs)) / (double)durationNs;
- saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+ mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
+ updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
+ volumeDurationNs, mVoiceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
+ saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
}
// reset statistics
mDeviceVolume = 0;
mDeviceTimeNs = endDeviceNs;
mVolumeTimeNs = endDeviceNs;
+ mMaxVoiceVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ mMinVoiceVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ mMaxVoiceVolumeDurationNs = 0;
+ mMinVoiceVolumeDurationNs = 0;
}
ALOGV("%s: new primary device:%#x old primary device:%#x", __func__, device, mPrimaryDevice);
mPrimaryDevice = device;
diff --git a/services/mediametrics/AudioPowerUsage.h b/services/mediametrics/AudioPowerUsage.h
index 7021902..b7215e6 100644
--- a/services/mediametrics/AudioPowerUsage.h
+++ b/services/mediametrics/AudioPowerUsage.h
@@ -26,6 +26,7 @@
namespace android::mediametrics {
+
class AudioAnalytics;
class AudioPowerUsage {
@@ -83,13 +84,21 @@
static bool deviceFromString(const std::string& device_string, int32_t& device);
static int32_t deviceFromStringPairs(const std::string& device_strings);
private:
- bool saveAsItem_l(int32_t device, int64_t duration, int32_t type, double average_vol)
- REQUIRES(mLock);
+ bool saveAsItem_l(int32_t device, int64_t duration, int32_t type, double average_vol,
+ int64_t max_volume_duration, double max_volume,
+ int64_t min_volume_duration, double min_volume)
+ REQUIRES(mLock);
void sendItem(const std::shared_ptr<const mediametrics::Item>& item) const;
void collect();
- bool saveAsItems_l(int32_t device, int64_t duration, int32_t type, double average_vol)
- REQUIRES(mLock);
-
+ bool saveAsItems_l(int32_t device, int64_t duration, int32_t type, double average_vol,
+ int64_t max_volume_duration, double max_volume,
+ int64_t min_volume_duration, double min_volume)
+ REQUIRES(mLock);
+ void updateMinMaxVolumeAndDuration(
+ const int64_t cur_max_volume_duration_ns, const double cur_max_volume,
+ const int64_t cur_min_volume_duration_ns, const double cur_min_volume,
+ int64_t& f_max_volume_duration_ns, double& f_max_volume,
+ int64_t& f_min_volume_duration_ns, double& f_min_volume);
AudioAnalytics * const mAudioAnalytics;
const std::shared_ptr<StatsdLog> mStatsdLog; // mStatsdLog is internally locked
const bool mDisabled;
@@ -100,6 +109,10 @@
double mVoiceVolume GUARDED_BY(mLock) = 0.;
double mDeviceVolume GUARDED_BY(mLock) = 0.;
+ double mMaxVoiceVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ double mMinVoiceVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ int64_t mMaxVoiceVolumeDurationNs GUARDED_BY(mLock) = 0;
+ int64_t mMinVoiceVolumeDurationNs GUARDED_BY(mLock) = 0;
int64_t mStartCallNs GUARDED_BY(mLock) = 0; // advisory only
int64_t mVolumeTimeNs GUARDED_BY(mLock) = 0;
int64_t mDeviceTimeNs GUARDED_BY(mLock) = 0;