blob: 095832c26f0ae36ba8bd186e596b37767acd758a [file] [log] [blame]
Joey Poomarin52989982020-03-05 17:40:49 +08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AudioPowerUsage"
19#include <utils/Log.h>
20
21#include "AudioAnalytics.h"
22#include "MediaMetricsService.h"
Andy Hung1ea842e2020-05-18 10:47:31 -070023#include "StringUtils.h"
Joey Poomarin52989982020-03-05 17:40:49 +080024#include <map>
25#include <sstream>
26#include <string>
27#include <audio_utils/clock.h>
Andy Hung76a772a2024-11-14 19:58:12 -080028#include <audio_utils/StringUtils.h>
Joey Poomarin52989982020-03-05 17:40:49 +080029#include <cutils/properties.h>
Vova Sharaienkof58455a2022-09-24 01:47:23 +000030#include <stats_media_metrics.h>
Joey Poomarin52989982020-03-05 17:40:49 +080031#include <sys/timerfd.h>
Mikhail Naganovdc6be0d2020-09-25 23:03:05 +000032#include <system/audio.h>
Joey Poomarin52989982020-03-05 17:40:49 +080033
34// property to disable audio power use metrics feature, default is enabled
35#define PROP_AUDIO_METRICS_DISABLED "persist.media.audio_metrics.power_usage_disabled"
36#define AUDIO_METRICS_DISABLED_DEFAULT (false)
37
Muhammad Qureshi087b37c2020-06-16 16:37:36 -070038// property to set how long to send audio power use metrics data to statsd, default is 24hrs
Joey Poomarin52989982020-03-05 17:40:49 +080039#define PROP_AUDIO_METRICS_INTERVAL_HR "persist.media.audio_metrics.interval_hr"
40#define INTERVAL_HR_DEFAULT (24)
41
42// for Audio Power Usage Metrics
43#define AUDIO_POWER_USAGE_KEY_AUDIO_USAGE "audio.power.usage"
44
45#define AUDIO_POWER_USAGE_PROP_DEVICE "device" // int32
46#define AUDIO_POWER_USAGE_PROP_DURATION_NS "durationNs" // int64
47#define AUDIO_POWER_USAGE_PROP_TYPE "type" // int32
48#define AUDIO_POWER_USAGE_PROP_VOLUME "volume" // double
Robert Lee36ac0412022-01-13 03:05:41 +000049#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS "minVolumeDurationNs" // int64
50#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME "minVolume" // double
51#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS "maxVolumeDurationNs" // int64
52#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME "maxVolume" // double
Joey Poomarin52989982020-03-05 17:40:49 +080053
54namespace android::mediametrics {
55
56/* static */
57bool AudioPowerUsage::typeFromString(const std::string& type_string, int32_t& type) {
58 static std::map<std::string, int32_t> typeTable = {
59 { "AUDIO_STREAM_VOICE_CALL", VOIP_CALL_TYPE },
60 { "AUDIO_STREAM_SYSTEM", MEDIA_TYPE },
61 { "AUDIO_STREAM_RING", RINGTONE_NOTIFICATION_TYPE },
62 { "AUDIO_STREAM_MUSIC", MEDIA_TYPE },
63 { "AUDIO_STREAM_ALARM", ALARM_TYPE },
64 { "AUDIO_STREAM_NOTIFICATION", RINGTONE_NOTIFICATION_TYPE },
65
66 { "AUDIO_CONTENT_TYPE_SPEECH", VOIP_CALL_TYPE },
67 { "AUDIO_CONTENT_TYPE_MUSIC", MEDIA_TYPE },
68 { "AUDIO_CONTENT_TYPE_MOVIE", MEDIA_TYPE },
69 { "AUDIO_CONTENT_TYPE_SONIFICATION", RINGTONE_NOTIFICATION_TYPE },
70
71 { "AUDIO_USAGE_MEDIA", MEDIA_TYPE },
72 { "AUDIO_USAGE_VOICE_COMMUNICATION", VOIP_CALL_TYPE },
73 { "AUDIO_USAGE_ALARM", ALARM_TYPE },
74 { "AUDIO_USAGE_NOTIFICATION", RINGTONE_NOTIFICATION_TYPE },
75
76 { "AUDIO_SOURCE_CAMCORDER", CAMCORDER_TYPE },
77 { "AUDIO_SOURCE_VOICE_COMMUNICATION", VOIP_CALL_TYPE },
78 { "AUDIO_SOURCE_DEFAULT", RECORD_TYPE },
79 { "AUDIO_SOURCE_MIC", RECORD_TYPE },
80 { "AUDIO_SOURCE_UNPROCESSED", RECORD_TYPE },
81 { "AUDIO_SOURCE_VOICE_RECOGNITION", RECORD_TYPE },
82 };
83
84 auto it = typeTable.find(type_string);
85 if (it == typeTable.end()) {
86 type = UNKNOWN_TYPE;
87 return false;
88 }
89
90 type = it->second;
91 return true;
92}
93
94/* static */
95bool AudioPowerUsage::deviceFromString(const std::string& device_string, int32_t& device) {
96 static std::map<std::string, int32_t> deviceTable = {
Poomarin Phloyphisut75f89f92024-05-24 06:08:18 +000097 { "AUDIO_DEVICE_OUT_EARPIECE", OUTPUT_EARPIECE },
98 { "AUDIO_DEVICE_OUT_SPEAKER_SAFE", OUTPUT_SPEAKER_SAFE },
99 { "AUDIO_DEVICE_OUT_SPEAKER", OUTPUT_SPEAKER },
100 { "AUDIO_DEVICE_OUT_WIRED_HEADSET", OUTPUT_WIRED_HEADSET },
101 { "AUDIO_DEVICE_OUT_WIRED_HEADPHONE", OUTPUT_WIRED_HEADSET },
102 { "AUDIO_DEVICE_OUT_BLUETOOTH_SCO", OUTPUT_BLUETOOTH_SCO },
103 { "AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET", OUTPUT_BLUETOOTH_SCO },
104 { "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP", OUTPUT_BLUETOOTH_A2DP },
105 { "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES", OUTPUT_BLUETOOTH_A2DP },
106 { "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER", OUTPUT_BLUETOOTH_A2DP },
107 { "AUDIO_DEVICE_OUT_BLE_HEADSET", OUTPUT_BLUETOOTH_BLE },
108 { "AUDIO_DEVICE_OUT_BLE_SPEAKER", OUTPUT_BLUETOOTH_BLE },
109 { "AUDIO_DEVICE_OUT_BLE_BROADCAST", OUTPUT_BLUETOOTH_BLE },
110 { "AUDIO_DEVICE_OUT_USB_HEADSET", OUTPUT_USB_HEADSET },
111 { "AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET", OUTPUT_DOCK },
112 { "AUDIO_DEVICE_OUT_HDMI", OUTPUT_HDMI },
Joey Poomarin52989982020-03-05 17:40:49 +0800113
114 { "AUDIO_DEVICE_IN_BUILTIN_MIC", INPUT_BUILTIN_MIC },
115 { "AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET", INPUT_BLUETOOTH_SCO },
Poomarin Phloyphisut75f89f92024-05-24 06:08:18 +0000116 { "AUDIO_DEVICE_IN_BLUETOOTH_BLE", INPUT_BLUETOOTH_BLE },
117 { "AUDIO_DEVICE_IN_BLE_HEADSET", INPUT_BLUETOOTH_BLE },
Joey Poomarin52989982020-03-05 17:40:49 +0800118 { "AUDIO_DEVICE_IN_WIRED_HEADSET", INPUT_WIRED_HEADSET_MIC },
119 { "AUDIO_DEVICE_IN_USB_DEVICE", INPUT_USB_HEADSET_MIC },
120 { "AUDIO_DEVICE_IN_BACK_MIC", INPUT_BUILTIN_BACK_MIC },
121 };
122
123 auto it = deviceTable.find(device_string);
124 if (it == deviceTable.end()) {
125 device = 0;
126 return false;
127 }
128
129 device = it->second;
130 return true;
131}
132
133int32_t AudioPowerUsage::deviceFromStringPairs(const std::string& device_strings) {
134 int32_t deviceMask = 0;
Andy Hung76a772a2024-11-14 19:58:12 -0800135 const auto devaddrvec = audio_utils::stringutils::getDeviceAddressPairs(device_strings);
Joey Poomarin52989982020-03-05 17:40:49 +0800136 for (const auto &[device, addr] : devaddrvec) {
137 int32_t combo_device = 0;
138 deviceFromString(device, combo_device);
139 deviceMask |= combo_device;
140 }
141 return deviceMask;
142}
143
Andy Hung5be90c82021-03-30 14:30:20 -0700144void AudioPowerUsage::sendItem(const std::shared_ptr<const mediametrics::Item>& item) const
Joey Poomarin52989982020-03-05 17:40:49 +0800145{
146 int32_t type;
147 if (!item->getInt32(AUDIO_POWER_USAGE_PROP_TYPE, &type)) return;
148
Andy Hung5be90c82021-03-30 14:30:20 -0700149 int32_t audio_device;
150 if (!item->getInt32(AUDIO_POWER_USAGE_PROP_DEVICE, &audio_device)) return;
Joey Poomarin52989982020-03-05 17:40:49 +0800151
152 int64_t duration_ns;
153 if (!item->getInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, &duration_ns)) return;
154
155 double volume;
156 if (!item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &volume)) return;
157
Robert Lee36ac0412022-01-13 03:05:41 +0000158 int64_t min_volume_duration_ns;
159 if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, &min_volume_duration_ns)) {
160 return;
161 }
162
163 double min_volume;
164 if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &min_volume)) return;
165
166 int64_t max_volume_duration_ns;
167 if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, &max_volume_duration_ns)) {
168 return;
169 }
170
171 double max_volume;
172 if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &max_volume)) return;
173
Andy Hung5be90c82021-03-30 14:30:20 -0700174 const int32_t duration_secs = (int32_t)(duration_ns / NANOS_PER_SECOND);
Robert Lee36ac0412022-01-13 03:05:41 +0000175 const int32_t min_volume_duration_secs = (int32_t)(min_volume_duration_ns / NANOS_PER_SECOND);
176 const int32_t max_volume_duration_secs = (int32_t)(max_volume_duration_ns / NANOS_PER_SECOND);
Vova Sharaienkof58455a2022-09-24 01:47:23 +0000177 const int result = stats::media_metrics::stats_write(stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED,
Andy Hung5be90c82021-03-30 14:30:20 -0700178 audio_device,
179 duration_secs,
Robert Lee36ac0412022-01-13 03:05:41 +0000180 (float)volume,
181 type,
182 min_volume_duration_secs,
183 (float)min_volume,
184 max_volume_duration_secs,
185 (float)max_volume);
Andy Hung5be90c82021-03-30 14:30:20 -0700186
187 std::stringstream log;
188 log << "result:" << result << " {"
189 << " mediametrics_audio_power_usage_data_reported:"
Vova Sharaienkof58455a2022-09-24 01:47:23 +0000190 << stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED
Andy Hung5be90c82021-03-30 14:30:20 -0700191 << " audio_device:" << audio_device
192 << " duration_secs:" << duration_secs
Robert Lee36ac0412022-01-13 03:05:41 +0000193 << " average_volume:" << (float)volume
Andy Hung5be90c82021-03-30 14:30:20 -0700194 << " type:" << type
Robert Lee36ac0412022-01-13 03:05:41 +0000195 << " min_volume_duration_secs:" << min_volume_duration_secs
196 << " min_volume:" << (float)min_volume
197 << " max_volume_duration_secs:" << max_volume_duration_secs
198 << " max_volume:" << (float)max_volume
Andy Hung5be90c82021-03-30 14:30:20 -0700199 << " }";
Vova Sharaienkof58455a2022-09-24 01:47:23 +0000200 mStatsdLog->log(stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
Joey Poomarin52989982020-03-05 17:40:49 +0800201}
202
Robert Lee36ac0412022-01-13 03:05:41 +0000203void AudioPowerUsage::updateMinMaxVolumeAndDuration(
204 const int64_t cur_max_volume_duration_ns, const double cur_max_volume,
205 const int64_t cur_min_volume_duration_ns, const double cur_min_volume,
206 int64_t& f_max_volume_duration_ns, double& f_max_volume,
207 int64_t& f_min_volume_duration_ns, double& f_min_volume)
208{
209 if (f_min_volume > cur_min_volume) {
210 f_min_volume = cur_min_volume;
211 f_min_volume_duration_ns = cur_min_volume_duration_ns;
212 } else if (f_min_volume == cur_min_volume) {
213 f_min_volume_duration_ns += cur_min_volume_duration_ns;
214 }
215 if (f_max_volume < cur_max_volume) {
216 f_max_volume = cur_max_volume;
217 f_max_volume_duration_ns = cur_max_volume_duration_ns;
218 } else if (f_max_volume == cur_max_volume) {
219 f_max_volume_duration_ns += cur_max_volume_duration_ns;
220 }
221}
222
Joey Poomarin52989982020-03-05 17:40:49 +0800223bool AudioPowerUsage::saveAsItem_l(
Robert Lee36ac0412022-01-13 03:05:41 +0000224 int32_t device, int64_t duration_ns, int32_t type, double average_vol,
225 int64_t max_volume_duration_ns, double max_volume,
226 int64_t min_volume_duration_ns, double min_volume)
Joey Poomarin52989982020-03-05 17:40:49 +0800227{
228 ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
Robert Lee36ac0412022-01-13 03:05:41 +0000229 (long long)duration_ns, average_vol);
Joey Poomarin52989982020-03-05 17:40:49 +0800230 if (duration_ns == 0) {
231 return true; // skip duration 0 usage
232 }
233 if (device == 0) {
234 return true; //ignore unknown device
235 }
236
Andy Hung3ab1b322020-05-18 10:47:31 -0700237 for (const auto& item : mItems) {
Joey Poomarin52989982020-03-05 17:40:49 +0800238 int32_t item_type = 0, item_device = 0;
239 double item_volume = 0.;
240 int64_t item_duration_ns = 0;
241 item->getInt32(AUDIO_POWER_USAGE_PROP_DEVICE, &item_device);
242 item->getInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, &item_duration_ns);
243 item->getInt32(AUDIO_POWER_USAGE_PROP_TYPE, &item_type);
244 item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &item_volume);
245
246 // aggregate by device and type
247 if (item_device == device && item_type == type) {
248 int64_t final_duration_ns = item_duration_ns + duration_ns;
249 double final_volume = (device & INPUT_DEVICE_BIT) ? 1.0:
Andy Hungc14ee142021-03-10 16:39:02 -0800250 ((item_volume * (double)item_duration_ns +
251 average_vol * (double)duration_ns) / (double)final_duration_ns);
Joey Poomarin52989982020-03-05 17:40:49 +0800252
253 item->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, final_duration_ns);
254 item->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, final_volume);
255 item->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
256
Robert Lee36ac0412022-01-13 03:05:41 +0000257 // Update the max/min volume and duration
258 int64_t final_min_volume_duration_ns;
259 int64_t final_max_volume_duration_ns;
260 double final_min_volume;
261 double final_max_volume;
262
263 item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
264 &final_min_volume_duration_ns);
265 item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &final_min_volume);
266 item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
267 &final_max_volume_duration_ns);
268 item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &final_max_volume);
269 updateMinMaxVolumeAndDuration(max_volume_duration_ns, max_volume,
270 min_volume_duration_ns, min_volume,
271 final_max_volume_duration_ns, final_max_volume,
272 final_min_volume_duration_ns, final_min_volume);
273 item->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
274 final_min_volume_duration_ns);
275 item->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, final_min_volume);
276 item->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
277 final_max_volume_duration_ns);
278 item->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, final_max_volume);
279
280 ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f) min(%lld, %f) max(%lld, %f)",
281 __func__,
Joey Poomarin52989982020-03-05 17:40:49 +0800282 device, type,
283 (long long)item_duration_ns, item_volume,
Robert Lee36ac0412022-01-13 03:05:41 +0000284 (long long)final_duration_ns, final_volume,
285 (long long)final_min_volume_duration_ns, final_min_volume,
286 (long long)final_max_volume_duration_ns, final_max_volume);
Joey Poomarin52989982020-03-05 17:40:49 +0800287
288 return true;
289 }
290 }
291
292 auto sitem = std::make_shared<mediametrics::Item>(AUDIO_POWER_USAGE_KEY_AUDIO_USAGE);
293 sitem->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
294 sitem->setInt32(AUDIO_POWER_USAGE_PROP_DEVICE, device);
295 sitem->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, duration_ns);
296 sitem->setInt32(AUDIO_POWER_USAGE_PROP_TYPE, type);
297 sitem->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, average_vol);
Robert Lee36ac0412022-01-13 03:05:41 +0000298 sitem->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, min_volume_duration_ns);
299 sitem->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, min_volume);
300 sitem->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, max_volume_duration_ns);
301 sitem->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, max_volume);
Joey Poomarin52989982020-03-05 17:40:49 +0800302 mItems.emplace_back(sitem);
303 return true;
304}
305
rogerfangcfb0ffb2020-07-16 16:27:16 +0800306bool AudioPowerUsage::saveAsItems_l(
Robert Lee36ac0412022-01-13 03:05:41 +0000307 int32_t device, int64_t duration_ns, int32_t type, double average_vol,
308 int64_t max_volume_duration, double max_volume,
309 int64_t min_volume_duration, double min_volume)
rogerfangcfb0ffb2020-07-16 16:27:16 +0800310{
311 ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
312 (long long)duration_ns, average_vol );
313 if (duration_ns == 0) {
314 return true; // skip duration 0 usage
315 }
316 if (device == 0) {
317 return true; //ignore unknown device
318 }
319
320 bool ret = false;
321 const int32_t input_bit = device & INPUT_DEVICE_BIT;
322 int32_t device_bits = device ^ input_bit;
323
324 while (device_bits != 0) {
325 int32_t tmp_device = device_bits & -device_bits; // get lowest bit
326 device_bits ^= tmp_device; // clear lowest bit
327 tmp_device |= input_bit; // restore input bit
Robert Lee36ac0412022-01-13 03:05:41 +0000328 ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol,
329 max_volume_duration, max_volume,
330 min_volume_duration, min_volume);
rogerfangcfb0ffb2020-07-16 16:27:16 +0800331
332 ALOGV("%s: device %#x recorded, remaining device_bits = %#x", __func__,
333 tmp_device, device_bits);
334 }
335 return ret;
336}
337
Joey Poomarin52989982020-03-05 17:40:49 +0800338void AudioPowerUsage::checkTrackRecord(
339 const std::shared_ptr<const mediametrics::Item>& item, bool isTrack)
340{
341 const std::string key = item->getKey();
342
343 int64_t deviceTimeNs = 0;
344 if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs)) {
345 return;
346 }
347 double deviceVolume = 1.;
Robert Lee36ac0412022-01-13 03:05:41 +0000348 int64_t maxVolumeDurationNs = 0;
349 double maxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
350 int64_t minVolumeDurationNs = 0;
351 double minVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
352 if (isTrack) {
353 if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
354 return;
355 }
356 if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, &maxVolumeDurationNs)) {
357 return;
358 }
359 if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, &maxVolume)) {
360 return;
361 }
362 if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, &minVolumeDurationNs)) {
363 return;
364 }
365 if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, &minVolume)) {
366 return;
367 }
Joey Poomarin52989982020-03-05 17:40:49 +0800368 }
Robert Lee36ac0412022-01-13 03:05:41 +0000369
Joey Poomarin52989982020-03-05 17:40:49 +0800370 int32_t type = 0;
371 std::string type_string;
372 if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
373 key, AMEDIAMETRICS_PROP_STREAMTYPE, &type_string) == OK) ||
374 (!isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
375 key, AMEDIAMETRICS_PROP_SOURCE, &type_string) == OK)) {
376 typeFromString(type_string, type);
377
378 if (isTrack && type == UNKNOWN_TYPE &&
379 mAudioAnalytics->mAnalyticsState->timeMachine().get(
380 key, AMEDIAMETRICS_PROP_USAGE, &type_string) == OK) {
381 typeFromString(type_string, type);
382 }
383 if (isTrack && type == UNKNOWN_TYPE &&
384 mAudioAnalytics->mAnalyticsState->timeMachine().get(
385 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &type_string) == OK) {
386 typeFromString(type_string, type);
387 }
388 ALOGV("type = %s => %d", type_string.c_str(), type);
389 }
390
391 int32_t device = 0;
392 std::string device_strings;
393 if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
394 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &device_strings) == OK) ||
395 (!isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
396 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &device_strings) == OK)) {
397
398 device = deviceFromStringPairs(device_strings);
399 ALOGV("device = %s => %d", device_strings.c_str(), device);
400 }
401 std::lock_guard l(mLock);
Robert Lee36ac0412022-01-13 03:05:41 +0000402 saveAsItems_l(device, deviceTimeNs, type, deviceVolume,
403 maxVolumeDurationNs, maxVolume, minVolumeDurationNs, minVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800404}
405
406void AudioPowerUsage::checkMode(const std::shared_ptr<const mediametrics::Item>& item)
407{
408 std::string mode;
409 if (!item->getString(AMEDIAMETRICS_PROP_AUDIOMODE, &mode)) return;
410
411 std::lock_guard l(mLock);
412 if (mode == mMode) return; // no change in mode.
413
414 if (mMode == "AUDIO_MODE_IN_CALL") { // leaving call mode
415 const int64_t endCallNs = item->getTimestamp();
416 const int64_t durationNs = endCallNs - mDeviceTimeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000417 const int64_t volumeDurationNs = endCallNs - mVolumeTimeNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800418 if (durationNs > 0) {
Andy Hung3ab1b322020-05-18 10:47:31 -0700419 mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
Robert Lee36ac0412022-01-13 03:05:41 +0000420 mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
421 updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
422 volumeDurationNs, mVoiceVolume,
423 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
424 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
425 saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
426 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
427 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800428 }
429 } else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
430 mStartCallNs = item->getTimestamp(); // advisory only
431
432 mDeviceVolume = 0;
433 mVolumeTimeNs = mStartCallNs;
434 mDeviceTimeNs = mStartCallNs;
435 }
436 ALOGV("%s: new mode:%s old mode:%s", __func__, mode.c_str(), mMode.c_str());
437 mMode = mode;
438}
439
440void AudioPowerUsage::checkVoiceVolume(const std::shared_ptr<const mediametrics::Item>& item)
441{
442 double voiceVolume = 0.;
443 if (!item->getDouble(AMEDIAMETRICS_PROP_VOICEVOLUME, &voiceVolume)) return;
444
445 std::lock_guard l(mLock);
446 if (voiceVolume == mVoiceVolume) return; // no change in volume
447
448 // we only track average device volume when we are in-call
449 if (mMode == "AUDIO_MODE_IN_CALL") {
450 const int64_t timeNs = item->getTimestamp();
451 const int64_t durationNs = timeNs - mDeviceTimeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000452 const int64_t volumeDurationNs = timeNs - mVolumeTimeNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800453 if (durationNs > 0) {
Andy Hung3ab1b322020-05-18 10:47:31 -0700454 mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
Robert Lee36ac0412022-01-13 03:05:41 +0000455 mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800456 mVolumeTimeNs = timeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000457 updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
458 volumeDurationNs, mVoiceVolume,
459 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
460 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800461 }
462 }
463 ALOGV("%s: new voice volume:%lf old voice volume:%lf", __func__, voiceVolume, mVoiceVolume);
464 mVoiceVolume = voiceVolume;
465}
466
467void AudioPowerUsage::checkCreatePatch(const std::shared_ptr<const mediametrics::Item>& item)
468{
469 std::string outputDevices;
470 if (!item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices)) return;
471
472 const std::string& key = item->getKey();
473 std::string flags;
474 if (mAudioAnalytics->mAnalyticsState->timeMachine().get(
475 key, AMEDIAMETRICS_PROP_FLAGS, &flags) != OK) return;
476
477 if (flags.find("AUDIO_OUTPUT_FLAG_PRIMARY") == std::string::npos) return;
478
479 const int32_t device = deviceFromStringPairs(outputDevices);
480
481 std::lock_guard l(mLock);
482 if (mPrimaryDevice == device) return;
483
484 if (mMode == "AUDIO_MODE_IN_CALL") {
485 // Save statistics
486 const int64_t endDeviceNs = item->getTimestamp();
487 const int64_t durationNs = endDeviceNs - mDeviceTimeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000488 const int64_t volumeDurationNs = endDeviceNs - mVolumeTimeNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800489 if (durationNs > 0) {
Andy Hung3ab1b322020-05-18 10:47:31 -0700490 mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
Robert Lee36ac0412022-01-13 03:05:41 +0000491 mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
492 updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
493 volumeDurationNs, mVoiceVolume,
494 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
495 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
496 saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
497 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
498 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800499 }
500 // reset statistics
501 mDeviceVolume = 0;
502 mDeviceTimeNs = endDeviceNs;
503 mVolumeTimeNs = endDeviceNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000504 mMaxVoiceVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
505 mMinVoiceVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
506 mMaxVoiceVolumeDurationNs = 0;
507 mMinVoiceVolumeDurationNs = 0;
Joey Poomarin52989982020-03-05 17:40:49 +0800508 }
509 ALOGV("%s: new primary device:%#x old primary device:%#x", __func__, device, mPrimaryDevice);
510 mPrimaryDevice = device;
511}
512
Andy Hung5be90c82021-03-30 14:30:20 -0700513AudioPowerUsage::AudioPowerUsage(
514 AudioAnalytics *audioAnalytics, const std::shared_ptr<StatsdLog>& statsdLog)
Joey Poomarin52989982020-03-05 17:40:49 +0800515 : mAudioAnalytics(audioAnalytics)
Andy Hung5be90c82021-03-30 14:30:20 -0700516 , mStatsdLog(statsdLog)
Joey Poomarin52989982020-03-05 17:40:49 +0800517 , mDisabled(property_get_bool(PROP_AUDIO_METRICS_DISABLED, AUDIO_METRICS_DISABLED_DEFAULT))
518 , mIntervalHours(property_get_int32(PROP_AUDIO_METRICS_INTERVAL_HR, INTERVAL_HR_DEFAULT))
519{
520 ALOGD("%s", __func__);
521 ALOGI_IF(mDisabled, "AudioPowerUsage is disabled.");
522 collect(); // send items
523}
524
525AudioPowerUsage::~AudioPowerUsage()
526{
527 ALOGD("%s", __func__);
528}
529
530void AudioPowerUsage::clear()
531{
532 std::lock_guard _l(mLock);
533 mItems.clear();
534}
535
536void AudioPowerUsage::collect()
537{
538 std::lock_guard _l(mLock);
539 for (const auto &item : mItems) {
540 sendItem(item);
541 }
542 mItems.clear();
543 mAudioAnalytics->mTimedAction.postIn(
544 mIntervalHours <= 0 ? std::chrono::seconds(5) : std::chrono::hours(mIntervalHours),
545 [this](){ collect(); });
546}
547
548std::pair<std::string, int32_t> AudioPowerUsage::dump(int limit) const {
549 if (limit <= 2) {
550 return {{}, 0};
551 }
552 std::lock_guard _l(mLock);
553 if (mDisabled) {
554 return {"AudioPowerUsage disabled\n", 1};
555 }
556 if (mItems.empty()) {
557 return {"AudioPowerUsage empty\n", 1};
558 }
559
560 int slot = 1;
561 std::stringstream ss;
Andy Hung8c830812023-12-14 14:52:26 -0800562 ss << "AudioPowerUsage interval " << mIntervalHours << " hours:\n";
Joey Poomarin52989982020-03-05 17:40:49 +0800563 for (const auto &item : mItems) {
564 if (slot >= limit - 1) {
565 ss << "-- AudioPowerUsage may be truncated!\n";
566 ++slot;
567 break;
568 }
569 ss << " " << slot << " " << item->toString() << "\n";
570 slot++;
571 }
572 return { ss.str(), slot };
573}
574
Andy Hung3ab1b322020-05-18 10:47:31 -0700575} // namespace android::mediametrics