• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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_TAG "APM::AudioPolicyEngine"
18 //#define LOG_NDEBUG 0
19 
20 //#define VERY_VERBOSE_LOGGING
21 #ifdef VERY_VERBOSE_LOGGING
22 #define ALOGVV ALOGV
23 #else
24 #define ALOGVV(a...) do { } while(0)
25 #endif
26 
27 #include "Engine.h"
28 #include <android-base/macros.h>
29 #include <AudioPolicyManagerObserver.h>
30 #include <PolicyAudioPort.h>
31 #include <IOProfile.h>
32 #include <AudioIODescriptorInterface.h>
33 #include <com_android_media_audioserver.h>
34 #include <policy.h>
35 #include <media/AudioContainers.h>
36 #include <utils/String8.h>
37 #include <utils/Log.h>
38 
39 namespace android::audio_policy {
40 
getLegacyStrategy()41 static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
42     static const std::vector<legacy_strategy_map> legacyStrategy = getLegacyStrategyMap();
43     return legacyStrategy;
44 }
45 
loadFromHalConfigWithFallback(const media::audio::common::AudioHalEngineConfig & aidlConfig)46 status_t Engine::loadFromHalConfigWithFallback(
47         const media::audio::common::AudioHalEngineConfig& aidlConfig) {
48     return loadWithFallback(aidlConfig);
49 }
50 
loadFromXmlConfigWithFallback(const std::string & xmlFilePath)51 status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
52     return loadWithFallback(xmlFilePath);
53 }
54 
55 template<typename T>
loadWithFallback(const T & configSource)56 status_t Engine::loadWithFallback(const T& configSource) {
57     auto result = EngineBase::loadAudioPolicyEngineConfig(configSource, false /*isConfigurable*/);
58     ALOGE_IF(result.nbSkippedElement != 0,
59              "Policy Engine configuration is partially invalid, skipped %zu elements",
60              result.nbSkippedElement);
61 
62     auto legacyStrategy = getLegacyStrategy();
63     for (const auto &strategy : legacyStrategy) {
64         mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
65     }
66 
67     return OK;
68 }
69 
70 
setForceUse(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)71 status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
72 {
73     switch(usage) {
74     case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
75         if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
76             config != AUDIO_POLICY_FORCE_NONE) {
77             ALOGW("setForceUse() invalid config %d for COMMUNICATION", config);
78             return BAD_VALUE;
79         }
80         break;
81     case AUDIO_POLICY_FORCE_FOR_MEDIA:
82         if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
83             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
84             config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
85             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
86             config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
87             ALOGW("setForceUse() invalid config %d for MEDIA", config);
88             return BAD_VALUE;
89         }
90         break;
91     case AUDIO_POLICY_FORCE_FOR_RECORD:
92         if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
93             config != AUDIO_POLICY_FORCE_NONE) {
94             ALOGW("setForceUse() invalid config %d for RECORD", config);
95             return BAD_VALUE;
96         }
97         break;
98     case AUDIO_POLICY_FORCE_FOR_DOCK:
99         if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
100             config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
101             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
102             config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
103             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
104             ALOGW("setForceUse() invalid config %d for DOCK", config);
105             return BAD_VALUE;
106         }
107         break;
108     case AUDIO_POLICY_FORCE_FOR_SYSTEM:
109         if (config != AUDIO_POLICY_FORCE_NONE &&
110             config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
111             ALOGW("setForceUse() invalid config %d for SYSTEM", config);
112             return BAD_VALUE;
113         }
114         break;
115     case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
116         if (config != AUDIO_POLICY_FORCE_NONE &&
117             config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
118             ALOGW("setForceUse() invalid config %d for HDMI_SYSTEM_AUDIO", config);
119             return BAD_VALUE;
120         }
121         break;
122     case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
123         if (config != AUDIO_POLICY_FORCE_NONE &&
124                 config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER &&
125                 config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS &&
126                 config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL) {
127             ALOGW("setForceUse() invalid config %d for ENCODED_SURROUND", config);
128             return BAD_VALUE;
129         }
130         break;
131     case AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:
132         if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_BT_BLE
133                 && config != AUDIO_POLICY_FORCE_NONE) {
134             ALOGW("setForceUse() invalid config %d for VIBRATE_RINGING", config);
135             return BAD_VALUE;
136         }
137         break;
138     default:
139         ALOGW("setForceUse() invalid usage %d", usage);
140         return BAD_VALUE;
141     }
142     return EngineBase::setForceUse(usage, config);
143 }
144 
isBtScoActive(DeviceVector & availableOutputDevices) const145 bool Engine::isBtScoActive(DeviceVector& availableOutputDevices) const {
146     // SCO is considered active if:
147     // 1) a SCO device is connected
148     // 2) the preferred device for PHONE strategy is BT SCO: this is controlled only by java
149     // AudioService and is only true if the SCO audio link as been confirmed active by BT.
150     if (availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllScoSet()).isEmpty()) {
151         return false;
152     }
153 
154     if (!audio_is_bluetooth_out_sco_device(
155             getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE))) {
156         return false;
157     }
158 
159     return true;
160 }
161 
filterOutputDevicesForStrategy(legacy_strategy strategy,DeviceVector & availableOutputDevices,const SwAudioOutputCollection & outputs) const162 void Engine::filterOutputDevicesForStrategy(legacy_strategy strategy,
163                                             DeviceVector& availableOutputDevices,
164                                             const SwAudioOutputCollection &outputs) const
165 {
166     DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
167 
168     if (com::android::media::audioserver::use_bt_sco_for_media()) {
169         // remove A2DP and LE Audio devices whenever BT SCO is in use
170         if (isBtScoActive(availableOutputDevices)) {
171             availableOutputDevices.remove(
172                 availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllA2dpSet()));
173             availableOutputDevices.remove(
174                 availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllBleSet()));
175         }
176     }
177 
178     switch (strategy) {
179     case STRATEGY_SONIFICATION_RESPECTFUL: {
180         if (!(isInCall() || outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL)))) {
181             // routing is same as media without the "remote" device
182             availableOutputDevices.remove(availableOutputDevices.getDevicesFromType(
183                     AUDIO_DEVICE_OUT_REMOTE_SUBMIX));
184         }
185         } break;
186     case STRATEGY_DTMF:
187     case STRATEGY_PHONE: {
188         // Force use of only devices on primary output if:
189         // - in call AND
190         //   - cannot route from voice call RX OR
191         //   - audio HAL version is < 3.0 and TX device is on the primary HW module
192         if (getPhoneState() == AUDIO_MODE_IN_CALL) {
193             sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
194             if (primaryOutput != nullptr) {
195                 audio_devices_t txDevice = AUDIO_DEVICE_NONE;
196                 sp<DeviceDescriptor> txDeviceDesc =
197                         getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
198                 if (txDeviceDesc != nullptr) {
199                     txDevice = txDeviceDesc->type();
200                 }
201                 DeviceVector availPrimaryInputDevices =
202                         availableInputDevices.getDevicesFromHwModule(
203                             primaryOutput->getModuleHandle());
204 
205                 // TODO: getPrimaryOutput return only devices from first module in
206                 // audio_policy_configuration.xml, hearing aid is not there, but it's
207                 // a primary device
208                 // FIXME: this is not the right way of solving this problem
209                 DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
210                         primaryOutput->supportedDevices().types());
211                 availPrimaryOutputDevices.add(
212                         availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
213 
214                 if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
215                                                      String8(""), AUDIO_FORMAT_DEFAULT) == nullptr)
216                     || ((availPrimaryInputDevices.getDevice(
217                             txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
218                      (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
219                     availableOutputDevices = availPrimaryOutputDevices;
220                 }
221             } else {
222                 ALOGE("%s, STRATEGY_PHONE: Primary output not found", __func__);
223             }
224         }
225         // Do not use A2DP devices when in call but use them when not in call
226         // (e.g for voice mail playback)
227         if (isInCall()) {
228             availableOutputDevices.remove(availableOutputDevices.getDevicesFromTypes({
229                     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
230                     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, }));
231         }
232         // If connected to a dock, never use the device speaker for calls
233         if (!availableOutputDevices.getDevicesFromTypes({AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET})
234                 .isEmpty()) {
235             availableOutputDevices.remove(
236                     availableOutputDevices.getDevicesFromTypes({AUDIO_DEVICE_OUT_SPEAKER}));
237         }
238         } break;
239     case STRATEGY_ACCESSIBILITY: {
240         // do not route accessibility prompts to a digital output currently configured with a
241         // compressed format as they would likely not be mixed and dropped.
242         for (size_t i = 0; i < outputs.size(); i++) {
243             sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
244             if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
245                 availableOutputDevices.remove(desc->devices().getDevicesFromTypes({
246                         AUDIO_DEVICE_OUT_HDMI, AUDIO_DEVICE_OUT_SPDIF,
247                         AUDIO_DEVICE_OUT_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_EARC}));
248             }
249         }
250         } break;
251     default:
252         break;
253     }
254 }
255 
remapStrategyFromContext(product_strategy_t strategy,const SwAudioOutputCollection & outputs) const256 product_strategy_t Engine::remapStrategyFromContext(product_strategy_t strategy,
257                                                  const SwAudioOutputCollection &outputs) const {
258     auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
259                           mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
260 
261     if (isInCall()) {
262         switch (legacyStrategy) {
263         case STRATEGY_ACCESSIBILITY:
264         case STRATEGY_DTMF:
265         case STRATEGY_MEDIA:
266         case STRATEGY_SONIFICATION:
267         case STRATEGY_SONIFICATION_RESPECTFUL:
268             legacyStrategy = STRATEGY_PHONE;
269             break;
270 
271         default:
272             return strategy;
273         }
274     } else {
275         switch (legacyStrategy) {
276         case STRATEGY_SONIFICATION_RESPECTFUL:
277         case STRATEGY_SONIFICATION:
278             if (outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_VOICE_CALL))) {
279                 legacyStrategy = STRATEGY_PHONE;
280             }
281             break;
282 
283         case STRATEGY_ACCESSIBILITY:
284             if (outputs.isActive(toVolumeSource(AUDIO_STREAM_RING)) ||
285                     outputs.isActive(toVolumeSource(AUDIO_STREAM_ALARM))) {
286                 legacyStrategy = STRATEGY_SONIFICATION;
287             }
288             break;
289 
290         default:
291             return strategy;
292         }
293     }
294     return getProductStrategyFromLegacy(legacyStrategy);
295 }
296 
getDevicesForStrategyInt(legacy_strategy strategy,DeviceVector availableOutputDevices,const SwAudioOutputCollection & outputs) const297 DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
298                                               DeviceVector availableOutputDevices,
299                                               const SwAudioOutputCollection &outputs) const
300 {
301     DeviceVector devices;
302 
303     switch (strategy) {
304 
305     case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
306         devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
307         break;
308 
309     case STRATEGY_PHONE: {
310         // TODO(b/243670205): remove this logic that gives preference to last removable devices
311         // once a UX decision has been made
312         devices = availableOutputDevices.getFirstDevicesFromTypes(
313                         getLastRemovableMediaDevices(GROUP_NONE, {
314                             // excluding HEARING_AID and BLE_HEADSET because Dialer uses
315                             // setCommunicationDevice to select them explicitly
316                             AUDIO_DEVICE_OUT_HEARING_AID,
317                             AUDIO_DEVICE_OUT_BLE_HEADSET,
318                             AUDIO_DEVICE_OUT_AUX_DIGITAL
319                             }));
320         if (!devices.isEmpty()) break;
321         devices = availableOutputDevices.getFirstDevicesFromTypes({
322                 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE,
323                 AUDIO_DEVICE_OUT_SPEAKER});
324     } break;
325 
326     case STRATEGY_SONIFICATION:
327     case STRATEGY_ENFORCED_AUDIBLE:
328         // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
329         // except:
330         //   - when in call where it doesn't default to STRATEGY_PHONE behavior
331         //   - in countries where not enforced in which case it follows STRATEGY_MEDIA
332 
333         if ((strategy == STRATEGY_SONIFICATION) ||
334                 (getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
335             // favor dock over speaker when available
336             devices = availableOutputDevices.getFirstDevicesFromTypes({
337                     AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_SPEAKER});
338         }
339 
340         // if SCO headset is connected and we are told to use it, play ringtone over
341         // speaker and BT SCO
342         if (!availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllScoSet()).isEmpty()
343                 && audio_is_bluetooth_out_sco_device(getPreferredDeviceTypeForLegacyStrategy(
344                             availableOutputDevices, STRATEGY_PHONE))) {
345             DeviceVector devices2 = availableOutputDevices.getFirstDevicesFromTypes({
346                     AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
347                     AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
348             // devices2 cannot be empty at this point
349             // Use ONLY Bluetooth SCO output when ringing in vibration mode
350             if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
351                         && (strategy == STRATEGY_ENFORCED_AUDIBLE))
352                     && (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING)
353                         == AUDIO_POLICY_FORCE_BT_SCO)) {
354                 devices = devices2;
355                 break;
356             }
357             // Use both Bluetooth SCO and phone default output when ringing in normal mode
358             if (strategy == STRATEGY_SONIFICATION) {
359                 devices.replaceDevicesByType(
360                         AUDIO_DEVICE_OUT_SPEAKER,
361                         availableOutputDevices.getDevicesFromType(
362                                 AUDIO_DEVICE_OUT_SPEAKER_SAFE));
363             }
364             devices.add(devices2);
365             break;
366         }
367 
368         // if LEA headset is connected and we are told to use it, play ringtone over
369         // speaker and BT LEA
370         if (!availableOutputDevices.getDevicesFromTypes(getAudioDeviceOutAllBleSet()).isEmpty()
371                 && audio_is_ble_out_device(getPreferredDeviceTypeForLegacyStrategy(
372                                        availableOutputDevices, STRATEGY_PHONE))) {
373             DeviceVector devices2;
374             devices2 = availableOutputDevices.getFirstDevicesFromTypes({
375                     AUDIO_DEVICE_OUT_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_SPEAKER});
376             // devices2 cannot be empty at this point
377             // Use ONLY Bluetooth LEA output when ringing in vibration mode
378             if (!((getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
379                         && (strategy == STRATEGY_ENFORCED_AUDIBLE))
380                     && (getForceUse(AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING)
381                                                == AUDIO_POLICY_FORCE_BT_BLE)) {
382                 devices = devices2;
383                 break;
384             }
385             // Use both Bluetooth LEA and phone default output when ringing in normal mode
386             if (strategy == STRATEGY_SONIFICATION) {
387                 devices.replaceDevicesByType(
388                         AUDIO_DEVICE_OUT_SPEAKER,
389                         availableOutputDevices.getDevicesFromType(
390                                 AUDIO_DEVICE_OUT_SPEAKER_SAFE));
391             }
392             devices.add(devices2);
393             break;
394         }
395 
396         // The second device used for sonification is the same as the device used by media strategy
397         FALLTHROUGH_INTENDED;
398 
399     case STRATEGY_DTMF:
400     case STRATEGY_ACCESSIBILITY:
401     case STRATEGY_SONIFICATION_RESPECTFUL:
402     case STRATEGY_REROUTING:
403     case STRATEGY_MEDIA: {
404         DeviceVector devices2;
405         if (strategy != STRATEGY_SONIFICATION) {
406             // no sonification on remote submix (e.g. WFD)
407             sp<DeviceDescriptor> remoteSubmix;
408             if ((remoteSubmix = availableOutputDevices.getDevice(
409                     AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
410                     AUDIO_FORMAT_DEFAULT)) != nullptr) {
411                 devices2.add(remoteSubmix);
412             }
413         }
414 
415         if ((devices2.isEmpty()) &&
416             (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
417             devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
418         }
419 
420         // LE audio broadcast device is only used if:
421         // - No call is active
422         // - the highest priority active strategy is not PHONE or TRANSMITTED_THROUGH_SPEAKER
423         // OR the LE audio unicast device is not active
424         if (devices2.isEmpty() && !isInCall()
425                 // also skipping routing queries from PHONE and TRANSMITTED_THROUGH_SPEAKER here
426                 // so this code is not dependent on breaks for other strategies above
427                 && (strategy != STRATEGY_PHONE)
428                 && (strategy != STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
429             legacy_strategy topActiveStrategy = STRATEGY_NONE;
430             for (const auto &ps : getOrderedProductStrategies()) {
431                 if (outputs.isStrategyActive(ps)) {
432                     topActiveStrategy =  mLegacyStrategyMap.find(ps) != end(mLegacyStrategyMap) ?
433                             mLegacyStrategyMap.at(ps) : STRATEGY_NONE;
434                     break;
435                 }
436             }
437 
438             if ((topActiveStrategy != STRATEGY_PHONE
439                         && topActiveStrategy != STRATEGY_TRANSMITTED_THROUGH_SPEAKER)
440                     || !outputs.isAnyDeviceTypeActive(getAudioDeviceOutLeAudioUnicastSet())) {
441                 devices2 =
442                         availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_BLE_BROADCAST);
443             }
444         }
445 
446         if (devices2.isEmpty() && (getLastRemovableMediaDevices().size() > 0)) {
447             std::vector<audio_devices_t> excludedDevices;
448             // no sonification on aux digital (e.g. HDMI)
449             if (strategy == STRATEGY_SONIFICATION) {
450                 excludedDevices.push_back(AUDIO_DEVICE_OUT_AUX_DIGITAL);
451             }
452             if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
453                 if (com::android::media::audioserver::use_bt_sco_for_media()) {
454                     if (isBtScoActive(availableOutputDevices)) {
455                         devices2 = availableOutputDevices.getFirstDevicesFromTypes(
456                                 { AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
457                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
458                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
459                     }
460                 }
461                 if (devices2.isEmpty()) {
462                     // Get the last connected device of wired and bluetooth a2dp
463                     devices2 = availableOutputDevices.getFirstDevicesFromTypes(
464                             getLastRemovableMediaDevices(GROUP_NONE, excludedDevices));
465                 }
466             } else {
467                 // Get the last connected device of wired except bluetooth a2dp
468                 devices2 = availableOutputDevices.getFirstDevicesFromTypes(
469                         getLastRemovableMediaDevices(GROUP_WIRED, excludedDevices));
470             }
471         }
472 
473         if ((devices2.isEmpty()) &&
474                 (getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK) == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
475             devices2 = availableOutputDevices.getDevicesFromType(
476                     AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET);
477         }
478 
479         if (devices2.isEmpty()) {
480             devices2 = availableOutputDevices.getFirstDevicesFromTypes({
481                         AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_SPEAKER});
482         }
483 
484         DeviceVector devices3;
485         if (strategy == STRATEGY_MEDIA) {
486             // ARC, SPDIF and AUX_LINE can co-exist with others.
487             devices3 = availableOutputDevices.getDevicesFromTypes({
488                     AUDIO_DEVICE_OUT_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_EARC,
489                     AUDIO_DEVICE_OUT_SPDIF, AUDIO_DEVICE_OUT_AUX_LINE,
490                     });
491         }
492 
493         devices2.add(devices3);
494         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
495         // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
496         devices.add(devices2);
497 
498         // If hdmi system audio mode is on, remove speaker out of output list.
499         if ((strategy == STRATEGY_MEDIA) &&
500             (getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
501                 AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
502             devices.remove(devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
503         }
504 
505         bool mediaActiveLocally =
506                 outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_MUSIC),
507                                         SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)
508                 || outputs.isActiveLocally(
509                     toVolumeSource(AUDIO_STREAM_ACCESSIBILITY),
510                     SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);
511 
512         bool ringActiveLocally = outputs.isActiveLocally(toVolumeSource(AUDIO_STREAM_RING), 0);
513         // - for STRATEGY_SONIFICATION and ringtone active:
514         // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
515         // - for STRATEGY_SONIFICATION_RESPECTFUL:
516         // if no media is playing on the device, check for mandatory use of "safe" speaker
517         // when media would have played on speaker, and the safe speaker path is available
518         if (strategy == STRATEGY_SONIFICATION || ringActiveLocally
519             || (strategy == STRATEGY_SONIFICATION_RESPECTFUL && !mediaActiveLocally)) {
520             devices.replaceDevicesByType(
521                     AUDIO_DEVICE_OUT_SPEAKER,
522                     availableOutputDevices.getDevicesFromType(
523                             AUDIO_DEVICE_OUT_SPEAKER_SAFE));
524         }
525         } break;
526 
527     case STRATEGY_CALL_ASSISTANT:
528         devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_TELEPHONY_TX);
529         break;
530 
531     case STRATEGY_NONE:
532         // Happens when internal strategies are processed ("rerouting", "patch"...)
533         break;
534 
535     default:
536         ALOGW("%s unknown strategy: %d", __func__, strategy);
537         break;
538     }
539 
540     if (devices.isEmpty()) {
541         ALOGI("%s no device found for strategy %d", __func__, strategy);
542         sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
543         if (defaultOutputDevice != nullptr) {
544             devices.add(defaultOutputDevice);
545         }
546         ALOGE_IF(devices.isEmpty(),
547                  "%s no default device defined", __func__);
548     }
549 
550     ALOGVV("%s strategy %d, device %s", __func__,
551            strategy, dumpDeviceTypes(devices.types()).c_str());
552     return devices;
553 }
554 
getPreferredAvailableDevicesForInputSource(const DeviceVector & availableInputDevices,audio_source_t inputSource) const555 DeviceVector Engine::getPreferredAvailableDevicesForInputSource(
556             const DeviceVector& availableInputDevices, audio_source_t inputSource) const {
557     DeviceVector preferredAvailableDevVec = {};
558     AudioDeviceTypeAddrVector preferredDevices;
559     const status_t status = getDevicesForRoleAndCapturePreset(
560             inputSource, DEVICE_ROLE_PREFERRED, preferredDevices);
561     if (status == NO_ERROR) {
562         // Only use preferred devices when they are all available.
563         preferredAvailableDevVec =
564                 availableInputDevices.getDevicesFromDeviceTypeAddrVec(preferredDevices);
565         if (preferredAvailableDevVec.size() == preferredDevices.size()) {
566             ALOGVV("%s using pref device %s for source %u",
567                    __func__, preferredAvailableDevVec.toString().c_str(), inputSource);
568             return preferredAvailableDevVec;
569         }
570     }
571     return preferredAvailableDevVec;
572 }
573 
getDisabledDevicesForInputSource(const DeviceVector & availableInputDevices,audio_source_t inputSource) const574 DeviceVector Engine::getDisabledDevicesForInputSource(
575             const DeviceVector& availableInputDevices, audio_source_t inputSource) const {
576     DeviceVector disabledDevices = {};
577     AudioDeviceTypeAddrVector disabledDevicesTypeAddr;
578     const status_t status = getDevicesForRoleAndCapturePreset(
579             inputSource, DEVICE_ROLE_DISABLED, disabledDevicesTypeAddr);
580     if (status == NO_ERROR) {
581         disabledDevices =
582                 availableInputDevices.getDevicesFromDeviceTypeAddrVec(disabledDevicesTypeAddr);
583     }
584     return disabledDevices;
585 }
586 
getDeviceForInputSource(audio_source_t inputSource) const587 sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
588 {
589     const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
590     const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
591     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
592     DeviceVector availableDevices = availableInputDevices;
593     sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
594     DeviceVector availablePrimaryDevices = primaryOutput == nullptr ? DeviceVector()
595             : availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
596     sp<DeviceDescriptor> device;
597 
598     // when a call is active, force device selection to match source VOICE_COMMUNICATION
599     // for most other input sources to avoid rerouting call TX audio
600     if (isInCall()) {
601         switch (inputSource) {
602         case AUDIO_SOURCE_DEFAULT:
603         case AUDIO_SOURCE_MIC:
604         case AUDIO_SOURCE_VOICE_RECOGNITION:
605         case AUDIO_SOURCE_UNPROCESSED:
606         case AUDIO_SOURCE_HOTWORD:
607         case AUDIO_SOURCE_CAMCORDER:
608         case AUDIO_SOURCE_VOICE_PERFORMANCE:
609         case AUDIO_SOURCE_ULTRASOUND:
610             inputSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
611             break;
612         default:
613             break;
614         }
615     }
616 
617     // Use the preferred device for the input source if it is available.
618     DeviceVector preferredInputDevices = getPreferredAvailableDevicesForInputSource(
619             availableDevices, inputSource);
620     if (!preferredInputDevices.isEmpty()) {
621         // Currently, only support single device for input. The public JAVA API also only
622         // support setting single device as preferred device. In that case, returning the
623         // first device is OK here.
624         return preferredInputDevices[0];
625     }
626     // Remove the disabled device for the input source from the available input device list.
627     DeviceVector disabledInputDevices = getDisabledDevicesForInputSource(
628             availableDevices, inputSource);
629     availableDevices.remove(disabledInputDevices);
630 
631     audio_devices_t commDeviceType =
632         getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE);
633 
634     switch (inputSource) {
635     case AUDIO_SOURCE_DEFAULT:
636     case AUDIO_SOURCE_MIC:
637         device = availableDevices.getDevice(
638                 AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
639         if (device != nullptr) break;
640         if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
641             device = availableDevices.getDevice(
642                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
643             if (device != nullptr) break;
644         }
645         device = availableDevices.getFirstExistingDevice({
646                 AUDIO_DEVICE_IN_WIRED_HEADSET,
647                 AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
648                 AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
649         break;
650 
651     case AUDIO_SOURCE_VOICE_COMMUNICATION:
652         // Allow only use of devices on primary input if in call and HAL does not support routing
653         // to voice call path.
654         if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
655                 (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
656                         String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
657             if (!availablePrimaryDevices.isEmpty()) {
658                 availableDevices = availablePrimaryDevices;
659             } else {
660                 ALOGE("%s, AUDIO_SOURCE_VOICE_COMMUNICATION: Primary devices not found", __func__);
661             }
662         }
663 
664         if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
665             // if SCO device is requested but no SCO device is available, fall back to default case
666             device = availableDevices.getDevice(
667                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
668             if (device != nullptr) {
669                 break;
670             }
671         }
672         switch (commDeviceType) {
673         case AUDIO_DEVICE_OUT_SPEAKER:
674             device = availableDevices.getFirstExistingDevice({
675                     AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
676                     AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_USB_HEADSET});
677             break;
678         case AUDIO_DEVICE_OUT_BLE_HEADSET:
679             device = availableDevices.getDevice(
680                     AUDIO_DEVICE_IN_BLE_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
681             if (device != nullptr) {
682                 break;
683             }
684             ALOGE("%s LE Audio selected for communication but input device not available",
685                     __func__);
686             FALLTHROUGH_INTENDED;
687         default:    // FORCE_NONE
688             device = availableDevices.getFirstExistingDevice({
689                     AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
690                     AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
691                     AUDIO_DEVICE_IN_BUILTIN_MIC});
692             break;
693         }
694         break;
695 
696     case AUDIO_SOURCE_VOICE_RECOGNITION:
697     case AUDIO_SOURCE_UNPROCESSED:
698         if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
699             device = availableDevices.getDevice(
700                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
701             if (device != nullptr) break;
702         }
703         // we need to make BLUETOOTH_BLE has higher priority than BUILTIN_MIC,
704         // because sometimes user want to do voice search by bt remote
705         // even if BUILDIN_MIC is available.
706         device = availableDevices.getFirstExistingDevice({
707                 AUDIO_DEVICE_IN_WIRED_HEADSET,
708                 AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
709                 AUDIO_DEVICE_IN_BLUETOOTH_BLE, AUDIO_DEVICE_IN_BUILTIN_MIC});
710 
711         break;
712     case AUDIO_SOURCE_HOTWORD:
713         // We should not use primary output criteria for Hotword but rather limit
714         // to devices attached to the same HW module as the build in mic
715         if (!availablePrimaryDevices.isEmpty()) {
716             availableDevices = availablePrimaryDevices;
717         } else {
718             ALOGE("%s, AUDIO_SOURCE_HOTWORD: Primary devices not found", __func__);
719         }
720         if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
721             device = availableDevices.getDevice(
722                     AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
723             if (device != nullptr) break;
724         }
725         device = availableDevices.getFirstExistingDevice({
726                 AUDIO_DEVICE_IN_WIRED_HEADSET,
727                 AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_IN_USB_DEVICE,
728                 AUDIO_DEVICE_IN_BUILTIN_MIC});
729         break;
730     case AUDIO_SOURCE_CAMCORDER:
731         // For a device without built-in mic, adding usb device
732         device = availableDevices.getFirstExistingDevice({
733                 AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC,
734                 AUDIO_DEVICE_IN_USB_DEVICE});
735         break;
736     case AUDIO_SOURCE_VOICE_DOWNLINK:
737     case AUDIO_SOURCE_VOICE_CALL:
738     case AUDIO_SOURCE_VOICE_UPLINK:
739         device = availableDevices.getDevice(
740                 AUDIO_DEVICE_IN_VOICE_CALL, String8(""), AUDIO_FORMAT_DEFAULT);
741         break;
742     case AUDIO_SOURCE_VOICE_PERFORMANCE:
743         device = availableDevices.getFirstExistingDevice({
744                 AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
745                 AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BLUETOOTH_BLE,
746                 AUDIO_DEVICE_IN_BUILTIN_MIC});
747         break;
748     case AUDIO_SOURCE_REMOTE_SUBMIX:
749         device = availableDevices.getDevice(
750                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8(""), AUDIO_FORMAT_DEFAULT);
751         break;
752     case AUDIO_SOURCE_FM_TUNER:
753         device = availableDevices.getDevice(
754                 AUDIO_DEVICE_IN_FM_TUNER, String8(""), AUDIO_FORMAT_DEFAULT);
755         break;
756     case AUDIO_SOURCE_ECHO_REFERENCE:
757         device = availableDevices.getDevice(
758                 AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT);
759         break;
760     case AUDIO_SOURCE_ULTRASOUND:
761         device = availableDevices.getFirstExistingDevice({
762                 AUDIO_DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BACK_MIC});
763         break;
764     default:
765         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
766         break;
767     }
768     if (device == nullptr) {
769         ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
770         device = availableDevices.getDevice(
771                 AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
772         ALOGE_IF(device == nullptr,
773                  "getDeviceForInputSource() no default device defined");
774     }
775 
776     ALOGV_IF(device != nullptr,
777              "getDeviceForInputSource()input source %d, device %08x",
778              inputSource, device->type());
779     return device;
780 }
781 
setStrategyDevices(const sp<ProductStrategy> & strategy,const DeviceVector & devices)782 void Engine::setStrategyDevices(const sp<ProductStrategy>& strategy, const DeviceVector &devices) {
783     strategy->setDeviceTypes(devices.types());
784     strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
785 }
786 
getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const787 product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
788     for (const auto& strategyMap : mLegacyStrategyMap) {
789         if (strategyMap.second == legacyStrategy) {
790             return strategyMap.first;
791         }
792     }
793     return PRODUCT_STRATEGY_NONE;
794 }
795 
getPreferredDeviceTypeForLegacyStrategy(const DeviceVector & availableOutputDevices,legacy_strategy legacyStrategy) const796 audio_devices_t Engine::getPreferredDeviceTypeForLegacyStrategy(
797         const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const {
798     product_strategy_t strategy = getProductStrategyFromLegacy(legacyStrategy);
799     DeviceVector devices = getPreferredAvailableDevicesForProductStrategy(
800             availableOutputDevices, strategy);
801     if (devices.size() > 0) {
802         return devices[0]->type();
803     }
804     return AUDIO_DEVICE_NONE;
805 }
806 
getDevicesForProductStrategy(product_strategy_t strategy) const807 DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
808     const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
809 
810     // Take context into account to remap product strategy before
811     // checking preferred device for strategy and applying default routing rules
812     strategy = remapStrategyFromContext(strategy, outputs);
813 
814     auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
815                           mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
816 
817     DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
818 
819     filterOutputDevicesForStrategy(legacyStrategy, availableOutputDevices, outputs);
820 
821     // check if this strategy has a preferred device that is available,
822     // if yes, give priority to it.
823     DeviceVector preferredAvailableDevVec =
824             getPreferredAvailableDevicesForProductStrategy(availableOutputDevices, strategy);
825     if (!preferredAvailableDevVec.isEmpty()) {
826         return preferredAvailableDevVec;
827     }
828 
829     // Remove all disabled devices from the available device list.
830     DeviceVector disabledDevVec =
831             getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
832     availableOutputDevices.remove(disabledDevVec);
833 
834     return getDevicesForStrategyInt(legacyStrategy,
835                                     availableOutputDevices,
836                                     outputs);
837 }
838 
getOutputDevicesForAttributes(const audio_attributes_t & attributes,const sp<DeviceDescriptor> & preferredDevice,bool fromCache) const839 DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
840                                                    const sp<DeviceDescriptor> &preferredDevice,
841                                                    bool fromCache) const
842 {
843     // First check for explict routing device
844     if (preferredDevice != nullptr) {
845         ALOGV("%s explicit Routing on device %s", __func__, preferredDevice->toString().c_str());
846         return DeviceVector(preferredDevice);
847     }
848     product_strategy_t strategy = getProductStrategyForAttributes(attributes);
849     const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
850     const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
851     //
852     // @TODO: what is the priority of explicit routing? Shall it be considered first as it used to
853     // be by APM?
854     //
855     // Honor explicit routing requests only if all active clients have a preferred route in which
856     // case the last active client route is used
857     sp<DeviceDescriptor> device = findPreferredDevice(outputs, strategy, availableOutputDevices);
858     if (device != nullptr) {
859         return DeviceVector(device);
860     }
861 
862     return fromCache? mDevicesForStrategies.at(strategy) : getDevicesForProductStrategy(strategy);
863 }
864 
getOutputDevicesForStream(audio_stream_type_t stream,bool fromCache) const865 DeviceVector Engine::getOutputDevicesForStream(audio_stream_type_t stream, bool fromCache) const
866 {
867     auto attributes = getAttributesForStreamType(stream);
868     return getOutputDevicesForAttributes(attributes, nullptr, fromCache);
869 }
870 
getInputDeviceForAttributes(const audio_attributes_t & attr,bool ignorePreferredDevice,uid_t uid,audio_session_t session,sp<AudioPolicyMix> * mix) const871 sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_t &attr,
872                                                          bool ignorePreferredDevice,
873                                                          uid_t uid,
874                                                          audio_session_t session,
875                                                          sp<AudioPolicyMix> *mix) const
876 {
877     const auto &policyMixes = getApmObserver()->getAudioPolicyMixCollection();
878     const auto availableInputDevices = getApmObserver()->getAvailableInputDevices();
879     const auto &inputs = getApmObserver()->getInputs();
880     std::string address;
881 
882     //
883     // Explicit Routing ??? what is the priority of explicit routing? Shall it be considered
884     // first as it used to be by APM?
885     //
886     // Honor explicit routing requests only if all active clients have a preferred route in which
887     // case the last active client route is used
888     sp<DeviceDescriptor> device;
889     if (!com::android::media::audioserver::conditionally_ignore_preferred_input_device()
890             || !ignorePreferredDevice) {
891         device = findPreferredDevice(inputs, attr.source, availableInputDevices);
892         if (device != nullptr) {
893             return device;
894         }
895     }
896 
897     device = policyMixes.getDeviceAndMixForInputSource(attr,
898                                                        availableInputDevices,
899                                                        uid,
900                                                        session,
901                                                        mix);
902     if (device != nullptr) {
903         return device;
904     }
905 
906     device = getDeviceForInputSource(attr.source);
907 
908     if (device != nullptr && device->type() == AUDIO_DEVICE_IN_ECHO_REFERENCE) {
909         sp<DeviceDescriptor> device2 = getInputDeviceForEchoRef(attr, availableInputDevices);
910         if (device2 != nullptr) {
911             return device2;
912         }
913     }
914 
915     if (device == nullptr || !audio_is_remote_submix_device(device->type())) {
916         // Return immediately if the device is null or it is not a remote submix device.
917         return device;
918     }
919 
920     // For remote submix device, try to find the device by address.
921     address = "0";
922     std::size_t pos;
923     std::string tags { attr.tags };
924     if ((pos = tags.find("addr=")) != std::string::npos) {
925         address = tags.substr(pos + std::strlen("addr="));
926     }
927     return availableInputDevices.getDevice(device->type(),
928                                            String8(address.c_str()),
929                                            AUDIO_FORMAT_DEFAULT);
930 }
931 
932 } // namespace android::audio_policy
933