blob: 5787e9efa2baaf3b4bc2c5f8ca6cd1ea2b4add63 [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>
28#include <cutils/properties.h>
29#include <statslog.h>
30#include <sys/timerfd.h>
Mikhail Naganovdc6be0d2020-09-25 23:03:05 +000031#include <system/audio.h>
Joey Poomarin52989982020-03-05 17:40:49 +080032
33// property to disable audio power use metrics feature, default is enabled
34#define PROP_AUDIO_METRICS_DISABLED "persist.media.audio_metrics.power_usage_disabled"
35#define AUDIO_METRICS_DISABLED_DEFAULT (false)
36
Muhammad Qureshi087b37c2020-06-16 16:37:36 -070037// property to set how long to send audio power use metrics data to statsd, default is 24hrs
Joey Poomarin52989982020-03-05 17:40:49 +080038#define PROP_AUDIO_METRICS_INTERVAL_HR "persist.media.audio_metrics.interval_hr"
39#define INTERVAL_HR_DEFAULT (24)
40
41// for Audio Power Usage Metrics
42#define AUDIO_POWER_USAGE_KEY_AUDIO_USAGE "audio.power.usage"
43
44#define AUDIO_POWER_USAGE_PROP_DEVICE "device" // int32
45#define AUDIO_POWER_USAGE_PROP_DURATION_NS "durationNs" // int64
46#define AUDIO_POWER_USAGE_PROP_TYPE "type" // int32
47#define AUDIO_POWER_USAGE_PROP_VOLUME "volume" // double
Robert Lee36ac0412022-01-13 03:05:41 +000048#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS "minVolumeDurationNs" // int64
49#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME "minVolume" // double
50#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS "maxVolumeDurationNs" // int64
51#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME "maxVolume" // double
Joey Poomarin52989982020-03-05 17:40:49 +080052
53namespace android::mediametrics {
54
55/* static */
56bool AudioPowerUsage::typeFromString(const std::string& type_string, int32_t& type) {
57 static std::map<std::string, int32_t> typeTable = {
58 { "AUDIO_STREAM_VOICE_CALL", VOIP_CALL_TYPE },
59 { "AUDIO_STREAM_SYSTEM", MEDIA_TYPE },
60 { "AUDIO_STREAM_RING", RINGTONE_NOTIFICATION_TYPE },
61 { "AUDIO_STREAM_MUSIC", MEDIA_TYPE },
62 { "AUDIO_STREAM_ALARM", ALARM_TYPE },
63 { "AUDIO_STREAM_NOTIFICATION", RINGTONE_NOTIFICATION_TYPE },
64
65 { "AUDIO_CONTENT_TYPE_SPEECH", VOIP_CALL_TYPE },
66 { "AUDIO_CONTENT_TYPE_MUSIC", MEDIA_TYPE },
67 { "AUDIO_CONTENT_TYPE_MOVIE", MEDIA_TYPE },
68 { "AUDIO_CONTENT_TYPE_SONIFICATION", RINGTONE_NOTIFICATION_TYPE },
69
70 { "AUDIO_USAGE_MEDIA", MEDIA_TYPE },
71 { "AUDIO_USAGE_VOICE_COMMUNICATION", VOIP_CALL_TYPE },
72 { "AUDIO_USAGE_ALARM", ALARM_TYPE },
73 { "AUDIO_USAGE_NOTIFICATION", RINGTONE_NOTIFICATION_TYPE },
74
75 { "AUDIO_SOURCE_CAMCORDER", CAMCORDER_TYPE },
76 { "AUDIO_SOURCE_VOICE_COMMUNICATION", VOIP_CALL_TYPE },
77 { "AUDIO_SOURCE_DEFAULT", RECORD_TYPE },
78 { "AUDIO_SOURCE_MIC", RECORD_TYPE },
79 { "AUDIO_SOURCE_UNPROCESSED", RECORD_TYPE },
80 { "AUDIO_SOURCE_VOICE_RECOGNITION", RECORD_TYPE },
81 };
82
83 auto it = typeTable.find(type_string);
84 if (it == typeTable.end()) {
85 type = UNKNOWN_TYPE;
86 return false;
87 }
88
89 type = it->second;
90 return true;
91}
92
93/* static */
94bool AudioPowerUsage::deviceFromString(const std::string& device_string, int32_t& device) {
95 static std::map<std::string, int32_t> deviceTable = {
96 { "AUDIO_DEVICE_OUT_EARPIECE", OUTPUT_EARPIECE },
97 { "AUDIO_DEVICE_OUT_SPEAKER_SAFE", OUTPUT_SPEAKER_SAFE },
98 { "AUDIO_DEVICE_OUT_SPEAKER", OUTPUT_SPEAKER },
99 { "AUDIO_DEVICE_OUT_WIRED_HEADSET", OUTPUT_WIRED_HEADSET },
100 { "AUDIO_DEVICE_OUT_WIRED_HEADPHONE", OUTPUT_WIRED_HEADSET },
101 { "AUDIO_DEVICE_OUT_BLUETOOTH_SCO", OUTPUT_BLUETOOTH_SCO },
102 { "AUDIO_DEVICE_OUT_BLUETOOTH_A2DP", OUTPUT_BLUETOOTH_A2DP },
103 { "AUDIO_DEVICE_OUT_USB_HEADSET", OUTPUT_USB_HEADSET },
104 { "AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET", OUTPUT_BLUETOOTH_SCO },
105
106 { "AUDIO_DEVICE_IN_BUILTIN_MIC", INPUT_BUILTIN_MIC },
107 { "AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET", INPUT_BLUETOOTH_SCO },
108 { "AUDIO_DEVICE_IN_WIRED_HEADSET", INPUT_WIRED_HEADSET_MIC },
109 { "AUDIO_DEVICE_IN_USB_DEVICE", INPUT_USB_HEADSET_MIC },
110 { "AUDIO_DEVICE_IN_BACK_MIC", INPUT_BUILTIN_BACK_MIC },
111 };
112
113 auto it = deviceTable.find(device_string);
114 if (it == deviceTable.end()) {
115 device = 0;
116 return false;
117 }
118
119 device = it->second;
120 return true;
121}
122
123int32_t AudioPowerUsage::deviceFromStringPairs(const std::string& device_strings) {
124 int32_t deviceMask = 0;
Andy Hung1ea842e2020-05-18 10:47:31 -0700125 const auto devaddrvec = stringutils::getDeviceAddressPairs(device_strings);
Joey Poomarin52989982020-03-05 17:40:49 +0800126 for (const auto &[device, addr] : devaddrvec) {
127 int32_t combo_device = 0;
128 deviceFromString(device, combo_device);
129 deviceMask |= combo_device;
130 }
131 return deviceMask;
132}
133
Andy Hung5be90c82021-03-30 14:30:20 -0700134void AudioPowerUsage::sendItem(const std::shared_ptr<const mediametrics::Item>& item) const
Joey Poomarin52989982020-03-05 17:40:49 +0800135{
136 int32_t type;
137 if (!item->getInt32(AUDIO_POWER_USAGE_PROP_TYPE, &type)) return;
138
Andy Hung5be90c82021-03-30 14:30:20 -0700139 int32_t audio_device;
140 if (!item->getInt32(AUDIO_POWER_USAGE_PROP_DEVICE, &audio_device)) return;
Joey Poomarin52989982020-03-05 17:40:49 +0800141
142 int64_t duration_ns;
143 if (!item->getInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, &duration_ns)) return;
144
145 double volume;
146 if (!item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &volume)) return;
147
Robert Lee36ac0412022-01-13 03:05:41 +0000148 int64_t min_volume_duration_ns;
149 if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, &min_volume_duration_ns)) {
150 return;
151 }
152
153 double min_volume;
154 if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &min_volume)) return;
155
156 int64_t max_volume_duration_ns;
157 if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, &max_volume_duration_ns)) {
158 return;
159 }
160
161 double max_volume;
162 if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &max_volume)) return;
163
Andy Hung5be90c82021-03-30 14:30:20 -0700164 const int32_t duration_secs = (int32_t)(duration_ns / NANOS_PER_SECOND);
Robert Lee36ac0412022-01-13 03:05:41 +0000165 const int32_t min_volume_duration_secs = (int32_t)(min_volume_duration_ns / NANOS_PER_SECOND);
166 const int32_t max_volume_duration_secs = (int32_t)(max_volume_duration_ns / NANOS_PER_SECOND);
Andy Hung5be90c82021-03-30 14:30:20 -0700167 const int result = android::util::stats_write(android::util::AUDIO_POWER_USAGE_DATA_REPORTED,
168 audio_device,
169 duration_secs,
Robert Lee36ac0412022-01-13 03:05:41 +0000170 (float)volume,
171 type,
172 min_volume_duration_secs,
173 (float)min_volume,
174 max_volume_duration_secs,
175 (float)max_volume);
Andy Hung5be90c82021-03-30 14:30:20 -0700176
177 std::stringstream log;
178 log << "result:" << result << " {"
179 << " mediametrics_audio_power_usage_data_reported:"
180 << android::util::AUDIO_POWER_USAGE_DATA_REPORTED
181 << " audio_device:" << audio_device
182 << " duration_secs:" << duration_secs
Robert Lee36ac0412022-01-13 03:05:41 +0000183 << " average_volume:" << (float)volume
Andy Hung5be90c82021-03-30 14:30:20 -0700184 << " type:" << type
Robert Lee36ac0412022-01-13 03:05:41 +0000185 << " min_volume_duration_secs:" << min_volume_duration_secs
186 << " min_volume:" << (float)min_volume
187 << " max_volume_duration_secs:" << max_volume_duration_secs
188 << " max_volume:" << (float)max_volume
Andy Hung5be90c82021-03-30 14:30:20 -0700189 << " }";
190 mStatsdLog->log(android::util::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
Joey Poomarin52989982020-03-05 17:40:49 +0800191}
192
Robert Lee36ac0412022-01-13 03:05:41 +0000193void AudioPowerUsage::updateMinMaxVolumeAndDuration(
194 const int64_t cur_max_volume_duration_ns, const double cur_max_volume,
195 const int64_t cur_min_volume_duration_ns, const double cur_min_volume,
196 int64_t& f_max_volume_duration_ns, double& f_max_volume,
197 int64_t& f_min_volume_duration_ns, double& f_min_volume)
198{
199 if (f_min_volume > cur_min_volume) {
200 f_min_volume = cur_min_volume;
201 f_min_volume_duration_ns = cur_min_volume_duration_ns;
202 } else if (f_min_volume == cur_min_volume) {
203 f_min_volume_duration_ns += cur_min_volume_duration_ns;
204 }
205 if (f_max_volume < cur_max_volume) {
206 f_max_volume = cur_max_volume;
207 f_max_volume_duration_ns = cur_max_volume_duration_ns;
208 } else if (f_max_volume == cur_max_volume) {
209 f_max_volume_duration_ns += cur_max_volume_duration_ns;
210 }
211}
212
Joey Poomarin52989982020-03-05 17:40:49 +0800213bool AudioPowerUsage::saveAsItem_l(
Robert Lee36ac0412022-01-13 03:05:41 +0000214 int32_t device, int64_t duration_ns, int32_t type, double average_vol,
215 int64_t max_volume_duration_ns, double max_volume,
216 int64_t min_volume_duration_ns, double min_volume)
Joey Poomarin52989982020-03-05 17:40:49 +0800217{
218 ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
Robert Lee36ac0412022-01-13 03:05:41 +0000219 (long long)duration_ns, average_vol);
Joey Poomarin52989982020-03-05 17:40:49 +0800220 if (duration_ns == 0) {
221 return true; // skip duration 0 usage
222 }
223 if (device == 0) {
224 return true; //ignore unknown device
225 }
226
Andy Hung3ab1b322020-05-18 10:47:31 -0700227 for (const auto& item : mItems) {
Joey Poomarin52989982020-03-05 17:40:49 +0800228 int32_t item_type = 0, item_device = 0;
229 double item_volume = 0.;
230 int64_t item_duration_ns = 0;
231 item->getInt32(AUDIO_POWER_USAGE_PROP_DEVICE, &item_device);
232 item->getInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, &item_duration_ns);
233 item->getInt32(AUDIO_POWER_USAGE_PROP_TYPE, &item_type);
234 item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &item_volume);
235
236 // aggregate by device and type
237 if (item_device == device && item_type == type) {
238 int64_t final_duration_ns = item_duration_ns + duration_ns;
239 double final_volume = (device & INPUT_DEVICE_BIT) ? 1.0:
Andy Hungc14ee142021-03-10 16:39:02 -0800240 ((item_volume * (double)item_duration_ns +
241 average_vol * (double)duration_ns) / (double)final_duration_ns);
Joey Poomarin52989982020-03-05 17:40:49 +0800242
243 item->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, final_duration_ns);
244 item->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, final_volume);
245 item->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
246
Robert Lee36ac0412022-01-13 03:05:41 +0000247 // Update the max/min volume and duration
248 int64_t final_min_volume_duration_ns;
249 int64_t final_max_volume_duration_ns;
250 double final_min_volume;
251 double final_max_volume;
252
253 item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
254 &final_min_volume_duration_ns);
255 item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &final_min_volume);
256 item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
257 &final_max_volume_duration_ns);
258 item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &final_max_volume);
259 updateMinMaxVolumeAndDuration(max_volume_duration_ns, max_volume,
260 min_volume_duration_ns, min_volume,
261 final_max_volume_duration_ns, final_max_volume,
262 final_min_volume_duration_ns, final_min_volume);
263 item->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
264 final_min_volume_duration_ns);
265 item->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, final_min_volume);
266 item->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
267 final_max_volume_duration_ns);
268 item->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, final_max_volume);
269
270 ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f) min(%lld, %f) max(%lld, %f)",
271 __func__,
Joey Poomarin52989982020-03-05 17:40:49 +0800272 device, type,
273 (long long)item_duration_ns, item_volume,
Robert Lee36ac0412022-01-13 03:05:41 +0000274 (long long)final_duration_ns, final_volume,
275 (long long)final_min_volume_duration_ns, final_min_volume,
276 (long long)final_max_volume_duration_ns, final_max_volume);
Joey Poomarin52989982020-03-05 17:40:49 +0800277
278 return true;
279 }
280 }
281
282 auto sitem = std::make_shared<mediametrics::Item>(AUDIO_POWER_USAGE_KEY_AUDIO_USAGE);
283 sitem->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
284 sitem->setInt32(AUDIO_POWER_USAGE_PROP_DEVICE, device);
285 sitem->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, duration_ns);
286 sitem->setInt32(AUDIO_POWER_USAGE_PROP_TYPE, type);
287 sitem->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, average_vol);
Robert Lee36ac0412022-01-13 03:05:41 +0000288 sitem->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, min_volume_duration_ns);
289 sitem->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, min_volume);
290 sitem->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, max_volume_duration_ns);
291 sitem->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, max_volume);
Joey Poomarin52989982020-03-05 17:40:49 +0800292 mItems.emplace_back(sitem);
293 return true;
294}
295
rogerfangcfb0ffb2020-07-16 16:27:16 +0800296bool AudioPowerUsage::saveAsItems_l(
Robert Lee36ac0412022-01-13 03:05:41 +0000297 int32_t device, int64_t duration_ns, int32_t type, double average_vol,
298 int64_t max_volume_duration, double max_volume,
299 int64_t min_volume_duration, double min_volume)
rogerfangcfb0ffb2020-07-16 16:27:16 +0800300{
301 ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
302 (long long)duration_ns, average_vol );
303 if (duration_ns == 0) {
304 return true; // skip duration 0 usage
305 }
306 if (device == 0) {
307 return true; //ignore unknown device
308 }
309
310 bool ret = false;
311 const int32_t input_bit = device & INPUT_DEVICE_BIT;
312 int32_t device_bits = device ^ input_bit;
313
314 while (device_bits != 0) {
315 int32_t tmp_device = device_bits & -device_bits; // get lowest bit
316 device_bits ^= tmp_device; // clear lowest bit
317 tmp_device |= input_bit; // restore input bit
Robert Lee36ac0412022-01-13 03:05:41 +0000318 ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol,
319 max_volume_duration, max_volume,
320 min_volume_duration, min_volume);
rogerfangcfb0ffb2020-07-16 16:27:16 +0800321
322 ALOGV("%s: device %#x recorded, remaining device_bits = %#x", __func__,
323 tmp_device, device_bits);
324 }
325 return ret;
326}
327
Joey Poomarin52989982020-03-05 17:40:49 +0800328void AudioPowerUsage::checkTrackRecord(
329 const std::shared_ptr<const mediametrics::Item>& item, bool isTrack)
330{
331 const std::string key = item->getKey();
332
333 int64_t deviceTimeNs = 0;
334 if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICETIMENS, &deviceTimeNs)) {
335 return;
336 }
337 double deviceVolume = 1.;
Robert Lee36ac0412022-01-13 03:05:41 +0000338 int64_t maxVolumeDurationNs = 0;
339 double maxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
340 int64_t minVolumeDurationNs = 0;
341 double minVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
342 if (isTrack) {
343 if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
344 return;
345 }
346 if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, &maxVolumeDurationNs)) {
347 return;
348 }
349 if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, &maxVolume)) {
350 return;
351 }
352 if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, &minVolumeDurationNs)) {
353 return;
354 }
355 if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, &minVolume)) {
356 return;
357 }
Joey Poomarin52989982020-03-05 17:40:49 +0800358 }
Robert Lee36ac0412022-01-13 03:05:41 +0000359
Joey Poomarin52989982020-03-05 17:40:49 +0800360 int32_t type = 0;
361 std::string type_string;
362 if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
363 key, AMEDIAMETRICS_PROP_STREAMTYPE, &type_string) == OK) ||
364 (!isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
365 key, AMEDIAMETRICS_PROP_SOURCE, &type_string) == OK)) {
366 typeFromString(type_string, type);
367
368 if (isTrack && type == UNKNOWN_TYPE &&
369 mAudioAnalytics->mAnalyticsState->timeMachine().get(
370 key, AMEDIAMETRICS_PROP_USAGE, &type_string) == OK) {
371 typeFromString(type_string, type);
372 }
373 if (isTrack && type == UNKNOWN_TYPE &&
374 mAudioAnalytics->mAnalyticsState->timeMachine().get(
375 key, AMEDIAMETRICS_PROP_CONTENTTYPE, &type_string) == OK) {
376 typeFromString(type_string, type);
377 }
378 ALOGV("type = %s => %d", type_string.c_str(), type);
379 }
380
381 int32_t device = 0;
382 std::string device_strings;
383 if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
384 key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &device_strings) == OK) ||
385 (!isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
386 key, AMEDIAMETRICS_PROP_INPUTDEVICES, &device_strings) == OK)) {
387
388 device = deviceFromStringPairs(device_strings);
389 ALOGV("device = %s => %d", device_strings.c_str(), device);
390 }
391 std::lock_guard l(mLock);
Robert Lee36ac0412022-01-13 03:05:41 +0000392 saveAsItems_l(device, deviceTimeNs, type, deviceVolume,
393 maxVolumeDurationNs, maxVolume, minVolumeDurationNs, minVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800394}
395
396void AudioPowerUsage::checkMode(const std::shared_ptr<const mediametrics::Item>& item)
397{
398 std::string mode;
399 if (!item->getString(AMEDIAMETRICS_PROP_AUDIOMODE, &mode)) return;
400
401 std::lock_guard l(mLock);
402 if (mode == mMode) return; // no change in mode.
403
404 if (mMode == "AUDIO_MODE_IN_CALL") { // leaving call mode
405 const int64_t endCallNs = item->getTimestamp();
406 const int64_t durationNs = endCallNs - mDeviceTimeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000407 const int64_t volumeDurationNs = endCallNs - mVolumeTimeNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800408 if (durationNs > 0) {
Andy Hung3ab1b322020-05-18 10:47:31 -0700409 mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
Robert Lee36ac0412022-01-13 03:05:41 +0000410 mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
411 updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
412 volumeDurationNs, mVoiceVolume,
413 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
414 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
415 saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
416 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
417 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800418 }
419 } else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
420 mStartCallNs = item->getTimestamp(); // advisory only
421
422 mDeviceVolume = 0;
423 mVolumeTimeNs = mStartCallNs;
424 mDeviceTimeNs = mStartCallNs;
425 }
426 ALOGV("%s: new mode:%s old mode:%s", __func__, mode.c_str(), mMode.c_str());
427 mMode = mode;
428}
429
430void AudioPowerUsage::checkVoiceVolume(const std::shared_ptr<const mediametrics::Item>& item)
431{
432 double voiceVolume = 0.;
433 if (!item->getDouble(AMEDIAMETRICS_PROP_VOICEVOLUME, &voiceVolume)) return;
434
435 std::lock_guard l(mLock);
436 if (voiceVolume == mVoiceVolume) return; // no change in volume
437
438 // we only track average device volume when we are in-call
439 if (mMode == "AUDIO_MODE_IN_CALL") {
440 const int64_t timeNs = item->getTimestamp();
441 const int64_t durationNs = timeNs - mDeviceTimeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000442 const int64_t volumeDurationNs = timeNs - mVolumeTimeNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800443 if (durationNs > 0) {
Andy Hung3ab1b322020-05-18 10:47:31 -0700444 mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
Robert Lee36ac0412022-01-13 03:05:41 +0000445 mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800446 mVolumeTimeNs = timeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000447 updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
448 volumeDurationNs, mVoiceVolume,
449 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
450 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800451 }
452 }
453 ALOGV("%s: new voice volume:%lf old voice volume:%lf", __func__, voiceVolume, mVoiceVolume);
454 mVoiceVolume = voiceVolume;
455}
456
457void AudioPowerUsage::checkCreatePatch(const std::shared_ptr<const mediametrics::Item>& item)
458{
459 std::string outputDevices;
460 if (!item->get(AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevices)) return;
461
462 const std::string& key = item->getKey();
463 std::string flags;
464 if (mAudioAnalytics->mAnalyticsState->timeMachine().get(
465 key, AMEDIAMETRICS_PROP_FLAGS, &flags) != OK) return;
466
467 if (flags.find("AUDIO_OUTPUT_FLAG_PRIMARY") == std::string::npos) return;
468
469 const int32_t device = deviceFromStringPairs(outputDevices);
470
471 std::lock_guard l(mLock);
472 if (mPrimaryDevice == device) return;
473
474 if (mMode == "AUDIO_MODE_IN_CALL") {
475 // Save statistics
476 const int64_t endDeviceNs = item->getTimestamp();
477 const int64_t durationNs = endDeviceNs - mDeviceTimeNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000478 const int64_t volumeDurationNs = endDeviceNs - mVolumeTimeNs;
Joey Poomarin52989982020-03-05 17:40:49 +0800479 if (durationNs > 0) {
Andy Hung3ab1b322020-05-18 10:47:31 -0700480 mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
Robert Lee36ac0412022-01-13 03:05:41 +0000481 mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
482 updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
483 volumeDurationNs, mVoiceVolume,
484 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
485 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
486 saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
487 mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
488 mMinVoiceVolumeDurationNs, mMinVoiceVolume);
Joey Poomarin52989982020-03-05 17:40:49 +0800489 }
490 // reset statistics
491 mDeviceVolume = 0;
492 mDeviceTimeNs = endDeviceNs;
493 mVolumeTimeNs = endDeviceNs;
Robert Lee36ac0412022-01-13 03:05:41 +0000494 mMaxVoiceVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
495 mMinVoiceVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
496 mMaxVoiceVolumeDurationNs = 0;
497 mMinVoiceVolumeDurationNs = 0;
Joey Poomarin52989982020-03-05 17:40:49 +0800498 }
499 ALOGV("%s: new primary device:%#x old primary device:%#x", __func__, device, mPrimaryDevice);
500 mPrimaryDevice = device;
501}
502
Andy Hung5be90c82021-03-30 14:30:20 -0700503AudioPowerUsage::AudioPowerUsage(
504 AudioAnalytics *audioAnalytics, const std::shared_ptr<StatsdLog>& statsdLog)
Joey Poomarin52989982020-03-05 17:40:49 +0800505 : mAudioAnalytics(audioAnalytics)
Andy Hung5be90c82021-03-30 14:30:20 -0700506 , mStatsdLog(statsdLog)
Joey Poomarin52989982020-03-05 17:40:49 +0800507 , mDisabled(property_get_bool(PROP_AUDIO_METRICS_DISABLED, AUDIO_METRICS_DISABLED_DEFAULT))
508 , mIntervalHours(property_get_int32(PROP_AUDIO_METRICS_INTERVAL_HR, INTERVAL_HR_DEFAULT))
509{
510 ALOGD("%s", __func__);
511 ALOGI_IF(mDisabled, "AudioPowerUsage is disabled.");
512 collect(); // send items
513}
514
515AudioPowerUsage::~AudioPowerUsage()
516{
517 ALOGD("%s", __func__);
518}
519
520void AudioPowerUsage::clear()
521{
522 std::lock_guard _l(mLock);
523 mItems.clear();
524}
525
526void AudioPowerUsage::collect()
527{
528 std::lock_guard _l(mLock);
529 for (const auto &item : mItems) {
530 sendItem(item);
531 }
532 mItems.clear();
533 mAudioAnalytics->mTimedAction.postIn(
534 mIntervalHours <= 0 ? std::chrono::seconds(5) : std::chrono::hours(mIntervalHours),
535 [this](){ collect(); });
536}
537
538std::pair<std::string, int32_t> AudioPowerUsage::dump(int limit) const {
539 if (limit <= 2) {
540 return {{}, 0};
541 }
542 std::lock_guard _l(mLock);
543 if (mDisabled) {
544 return {"AudioPowerUsage disabled\n", 1};
545 }
546 if (mItems.empty()) {
547 return {"AudioPowerUsage empty\n", 1};
548 }
549
550 int slot = 1;
551 std::stringstream ss;
552 ss << "AudioPowerUsage:\n";
553 for (const auto &item : mItems) {
554 if (slot >= limit - 1) {
555 ss << "-- AudioPowerUsage may be truncated!\n";
556 ++slot;
557 break;
558 }
559 ss << " " << slot << " " << item->toString() << "\n";
560 slot++;
561 }
562 return { ss.str(), slot };
563}
564
Andy Hung3ab1b322020-05-18 10:47:31 -0700565} // namespace android::mediametrics