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