| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2009 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 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 17 | #define LOG_TAG "AudioPolicyManager" | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 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 | // A device mask for all audio input devices that are considered "virtual" when evaluating | 
 | 28 | // active inputs in getActiveInput() | 
| Hochi Huang | 327cb70 | 2014-09-21 09:47:31 +0800 | [diff] [blame] | 29 | #define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 30 | // A device mask for all audio output devices that are considered "remote" when evaluating | 
 | 31 | // active output devices in isStreamActiveRemotely() | 
 | 32 | #define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 33 | // A device mask for all audio input and output devices where matching inputs/outputs on device | 
 | 34 | // type alone is not enough: the address must match too | 
 | 35 | #define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \ | 
 | 36 |                                             AUDIO_DEVICE_OUT_REMOTE_SUBMIX) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 37 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 38 | #include <inttypes.h> | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 39 | #include <math.h> | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 40 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 41 | #include <cutils/properties.h> | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 42 | #include <utils/Log.h> | 
 | 43 | #include <hardware/audio.h> | 
 | 44 | #include <hardware/audio_effect.h> | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 45 | #include <media/AudioParameter.h> | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 46 | #include <media/AudioPolicyHelper.h> | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 47 | #include <soundtrigger/SoundTrigger.h> | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 48 | #include "AudioPolicyManager.h" | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 49 | #include "audio_policy_conf.h" | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 50 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 51 | namespace android { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 52 |  | 
 | 53 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 54 | // Definitions for audio_policy.conf file parsing | 
 | 55 | // ---------------------------------------------------------------------------- | 
 | 56 |  | 
 | 57 | struct StringToEnum { | 
 | 58 |     const char *name; | 
 | 59 |     uint32_t value; | 
 | 60 | }; | 
 | 61 |  | 
 | 62 | #define STRING_TO_ENUM(string) { #string, string } | 
 | 63 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | 
 | 64 |  | 
 | 65 | const StringToEnum sDeviceNameToEnumTable[] = { | 
 | 66 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE), | 
 | 67 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER), | 
| Jon Eklund | 11c9fb1 | 2014-06-23 14:47:03 -0500 | [diff] [blame] | 68 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 69 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET), | 
 | 70 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE), | 
 | 71 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO), | 
 | 72 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET), | 
 | 73 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT), | 
 | 74 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO), | 
 | 75 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP), | 
 | 76 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES), | 
 | 77 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), | 
 | 78 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP), | 
 | 79 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 80 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 81 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET), | 
 | 82 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET), | 
 | 83 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY), | 
 | 84 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE), | 
 | 85 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB), | 
 | 86 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 87 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX), | 
 | 88 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE), | 
 | 89 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC), | 
 | 90 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF), | 
 | 91 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM), | 
| Eric Laurent | e1d37b7 | 2014-07-29 10:26:26 -0700 | [diff] [blame] | 92 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE), | 
| Eric Laurent | a57ab8d | 2014-07-30 10:01:42 -0500 | [diff] [blame] | 93 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 94 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), | 
 | 95 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), | 
 | 96 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO), | 
 | 97 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET), | 
 | 98 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 99 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 100 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX), | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 101 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 102 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC), | 
 | 103 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX), | 
 | 104 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET), | 
 | 105 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET), | 
 | 106 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY), | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 107 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 108 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER), | 
 | 109 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER), | 
 | 110 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE), | 
 | 111 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF), | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 112 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP), | 
| Terry Heo | 7999a22 | 2014-06-27 15:23:36 +0900 | [diff] [blame] | 113 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 114 | }; | 
 | 115 |  | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 116 | const StringToEnum sOutputFlagNameToEnumTable[] = { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 117 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT), | 
 | 118 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY), | 
 | 119 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST), | 
 | 120 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), | 
 | 121 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), | 
 | 122 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING), | 
| Eric Laurent | 93c3d41 | 2014-08-01 14:48:35 -0700 | [diff] [blame] | 123 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 124 | }; | 
 | 125 |  | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 126 | const StringToEnum sInputFlagNameToEnumTable[] = { | 
 | 127 |     STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST), | 
 | 128 |     STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD), | 
 | 129 | }; | 
 | 130 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 131 | const StringToEnum sFormatNameToEnumTable[] = { | 
 | 132 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT), | 
 | 133 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT), | 
 | 134 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT), | 
 | 135 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT), | 
 | 136 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT), | 
 | 137 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED), | 
 | 138 |     STRING_TO_ENUM(AUDIO_FORMAT_MP3), | 
 | 139 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC), | 
| aarti jadhav-gaikwad | 2829edc | 2014-06-18 15:25:26 +0530 | [diff] [blame] | 140 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_MAIN), | 
 | 141 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC), | 
 | 142 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_SSR), | 
 | 143 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LTP), | 
 | 144 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1), | 
 | 145 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_SCALABLE), | 
 | 146 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ERLC), | 
 | 147 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LD), | 
 | 148 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2), | 
 | 149 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ELD), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 150 |     STRING_TO_ENUM(AUDIO_FORMAT_VORBIS), | 
| Eric Laurent | ab5cdba | 2014-06-09 17:22:27 -0700 | [diff] [blame] | 151 |     STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1), | 
 | 152 |     STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2), | 
 | 153 |     STRING_TO_ENUM(AUDIO_FORMAT_OPUS), | 
 | 154 |     STRING_TO_ENUM(AUDIO_FORMAT_AC3), | 
 | 155 |     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 156 | }; | 
 | 157 |  | 
 | 158 | const StringToEnum sOutChannelsNameToEnumTable[] = { | 
 | 159 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO), | 
 | 160 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO), | 
| Andy Hung | 3a0fe12 | 2014-07-29 17:56:46 -0700 | [diff] [blame] | 161 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 162 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), | 
 | 163 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1), | 
 | 164 | }; | 
 | 165 |  | 
 | 166 | const StringToEnum sInChannelsNameToEnumTable[] = { | 
 | 167 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO), | 
 | 168 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO), | 
 | 169 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK), | 
 | 170 | }; | 
 | 171 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 172 | const StringToEnum sGainModeNameToEnumTable[] = { | 
 | 173 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT), | 
 | 174 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS), | 
 | 175 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP), | 
 | 176 | }; | 
 | 177 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 178 |  | 
 | 179 | uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table, | 
 | 180 |                                               size_t size, | 
 | 181 |                                               const char *name) | 
 | 182 | { | 
 | 183 |     for (size_t i = 0; i < size; i++) { | 
 | 184 |         if (strcmp(table[i].name, name) == 0) { | 
 | 185 |             ALOGV("stringToEnum() found %s", table[i].name); | 
 | 186 |             return table[i].value; | 
 | 187 |         } | 
 | 188 |     } | 
 | 189 |     return 0; | 
 | 190 | } | 
 | 191 |  | 
 | 192 | const char *AudioPolicyManager::enumToString(const struct StringToEnum *table, | 
 | 193 |                                               size_t size, | 
 | 194 |                                               uint32_t value) | 
 | 195 | { | 
 | 196 |     for (size_t i = 0; i < size; i++) { | 
 | 197 |         if (table[i].value == value) { | 
 | 198 |             return table[i].name; | 
 | 199 |         } | 
 | 200 |     } | 
 | 201 |     return ""; | 
 | 202 | } | 
 | 203 |  | 
 | 204 | bool AudioPolicyManager::stringToBool(const char *value) | 
 | 205 | { | 
 | 206 |     return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0)); | 
 | 207 | } | 
 | 208 |  | 
 | 209 |  | 
 | 210 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 211 | // AudioPolicyInterface implementation | 
 | 212 | // ---------------------------------------------------------------------------- | 
 | 213 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 214 | status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 215 |                                                           audio_policy_dev_state_t state, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 216 |                                                   const char *device_address) | 
 | 217 | { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 218 |     return setDeviceConnectionStateInt(device, state, device_address); | 
 | 219 | } | 
 | 220 |  | 
 | 221 | status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device, | 
 | 222 |                                                           audio_policy_dev_state_t state, | 
 | 223 |                                                   const char *device_address) | 
 | 224 | { | 
| Eric Laurent | 2222601 | 2014-08-01 17:00:54 -0700 | [diff] [blame] | 225 |     String8 address = (device_address == NULL) ? String8("") : String8(device_address); | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 226 |     // handle legacy remote submix case where the address was not always specified | 
 | 227 |     if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) { | 
 | 228 |         address = String8("0"); | 
 | 229 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 230 |  | 
| Eric Laurent | 2222601 | 2014-08-01 17:00:54 -0700 | [diff] [blame] | 231 |     ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", | 
 | 232 |             device, state, address.string()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 233 |  | 
 | 234 |     // connect/disconnect only 1 device at a time | 
 | 235 |     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE; | 
 | 236 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 237 |     // handle output devices | 
 | 238 |     if (audio_is_output_device(device)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 239 |         SortedVector <audio_io_handle_t> outputs; | 
 | 240 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 241 |         sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 242 |         devDesc->mAddress = address; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 243 |         ssize_t index = mAvailableOutputDevices.indexOf(devDesc); | 
 | 244 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 245 |         // save a copy of the opened output descriptors before any output is opened or closed | 
 | 246 |         // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies() | 
 | 247 |         mPreviousOutputs = mOutputs; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 248 |         switch (state) | 
 | 249 |         { | 
 | 250 |         // handle output device connection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 251 |         case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 252 |             if (index >= 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 253 |                 ALOGW("setDeviceConnectionState() device already connected: %x", device); | 
 | 254 |                 return INVALID_OPERATION; | 
 | 255 |             } | 
 | 256 |             ALOGV("setDeviceConnectionState() connecting device %x", device); | 
 | 257 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 258 |             // register new device as available | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 259 |             index = mAvailableOutputDevices.add(devDesc); | 
 | 260 |             if (index >= 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 261 |                 sp<HwModule> module = getModuleForDevice(device); | 
| Eric Laurent | cf817a2 | 2014-08-04 20:36:31 -0700 | [diff] [blame] | 262 |                 if (module == 0) { | 
 | 263 |                     ALOGD("setDeviceConnectionState() could not find HW module for device %08x", | 
 | 264 |                           device); | 
 | 265 |                     mAvailableOutputDevices.remove(devDesc); | 
 | 266 |                     return INVALID_OPERATION; | 
 | 267 |                 } | 
 | 268 |                 mAvailableOutputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 269 |                 mAvailableOutputDevices[index]->mModule = module; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 270 |             } else { | 
 | 271 |                 return NO_MEMORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 272 |             } | 
 | 273 |  | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 274 |             if (checkOutputsForDevice(devDesc, state, outputs, address) != NO_ERROR) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 275 |                 mAvailableOutputDevices.remove(devDesc); | 
 | 276 |                 return INVALID_OPERATION; | 
 | 277 |             } | 
 | 278 |             // outputs should never be empty here | 
 | 279 |             ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" | 
 | 280 |                     "checkOutputsForDevice() returned no outputs but status OK"); | 
 | 281 |             ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs", | 
 | 282 |                   outputs.size()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 283 |             break; | 
 | 284 |         // handle output device disconnection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 285 |         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 286 |             if (index < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 287 |                 ALOGW("setDeviceConnectionState() device not connected: %x", device); | 
 | 288 |                 return INVALID_OPERATION; | 
 | 289 |             } | 
 | 290 |  | 
| Paul McLean | 5c477aa | 2014-08-20 16:47:57 -0700 | [diff] [blame] | 291 |             ALOGV("setDeviceConnectionState() disconnecting output device %x", device); | 
 | 292 |  | 
 | 293 |             // Set Disconnect to HALs | 
 | 294 |             AudioParameter param = AudioParameter(address); | 
 | 295 |             param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device); | 
 | 296 |             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString()); | 
 | 297 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 298 |             // remove device from available output devices | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 299 |             mAvailableOutputDevices.remove(devDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 300 |  | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 301 |             checkOutputsForDevice(devDesc, state, outputs, address); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 302 |             } break; | 
 | 303 |  | 
 | 304 |         default: | 
 | 305 |             ALOGE("setDeviceConnectionState() invalid state: %x", state); | 
 | 306 |             return BAD_VALUE; | 
 | 307 |         } | 
 | 308 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 309 |         // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP | 
 | 310 |         // output is suspended before any tracks are moved to it | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 311 |         checkA2dpSuspend(); | 
 | 312 |         checkOutputForAllStrategies(); | 
 | 313 |         // outputs must be closed after checkOutputForAllStrategies() is executed | 
 | 314 |         if (!outputs.isEmpty()) { | 
 | 315 |             for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 316 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 317 |                 // close unused outputs after device disconnection or direct outputs that have been | 
 | 318 |                 // opened by checkOutputsForDevice() to query dynamic parameters | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 319 |                 if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 320 |                         (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && | 
 | 321 |                          (desc->mDirectOpenCount == 0))) { | 
 | 322 |                     closeOutput(outputs[i]); | 
 | 323 |                 } | 
 | 324 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 325 |             // check again after closing A2DP output to reset mA2dpSuspended if needed | 
 | 326 |             checkA2dpSuspend(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 327 |         } | 
 | 328 |  | 
 | 329 |         updateDevicesAndOutputs(); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 330 |         if (mPhoneState == AUDIO_MODE_IN_CALL) { | 
 | 331 |             audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/); | 
 | 332 |             updateCallRouting(newDevice); | 
 | 333 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 334 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 335 |             audio_io_handle_t output = mOutputs.keyAt(i); | 
 | 336 |             if ((mPhoneState != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) { | 
 | 337 |                 audio_devices_t newDevice = getNewOutputDevice(mOutputs.keyAt(i), | 
 | 338 |                                                                true /*fromCache*/); | 
 | 339 |                 // do not force device change on duplicated output because if device is 0, it will | 
 | 340 |                 // also force a device 0 for the two outputs it is duplicated to which may override | 
 | 341 |                 // a valid device selection on those outputs. | 
 | 342 |                 bool force = !mOutputs.valueAt(i)->isDuplicated() | 
 | 343 |                         && (!deviceDistinguishesOnAddress(device) | 
 | 344 |                                 // always force when disconnecting (a non-duplicated device) | 
 | 345 |                                 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)); | 
 | 346 |                 setOutputDevice(output, newDevice, force, 0); | 
 | 347 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 348 |         } | 
 | 349 |  | 
| Eric Laurent | 72aa32f | 2014-05-30 18:51:48 -0700 | [diff] [blame] | 350 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | b71e58b | 2014-05-29 16:08:11 -0700 | [diff] [blame] | 351 |         return NO_ERROR; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 352 |     }  // end if is output device | 
 | 353 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 354 |     // handle input devices | 
 | 355 |     if (audio_is_input_device(device)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 356 |         SortedVector <audio_io_handle_t> inputs; | 
 | 357 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 358 |         sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 359 |         devDesc->mAddress = address; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 360 |         ssize_t index = mAvailableInputDevices.indexOf(devDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 361 |         switch (state) | 
 | 362 |         { | 
 | 363 |         // handle input device connection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 364 |         case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 365 |             if (index >= 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 366 |                 ALOGW("setDeviceConnectionState() device already connected: %d", device); | 
 | 367 |                 return INVALID_OPERATION; | 
 | 368 |             } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 369 |             sp<HwModule> module = getModuleForDevice(device); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 370 |             if (module == NULL) { | 
 | 371 |                 ALOGW("setDeviceConnectionState(): could not find HW module for device %08x", | 
 | 372 |                       device); | 
 | 373 |                 return INVALID_OPERATION; | 
 | 374 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 375 |             if (checkInputsForDevice(device, state, inputs, address) != NO_ERROR) { | 
 | 376 |                 return INVALID_OPERATION; | 
 | 377 |             } | 
 | 378 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 379 |             index = mAvailableInputDevices.add(devDesc); | 
 | 380 |             if (index >= 0) { | 
 | 381 |                 mAvailableInputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 382 |                 mAvailableInputDevices[index]->mModule = module; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 383 |             } else { | 
 | 384 |                 return NO_MEMORY; | 
 | 385 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 386 |         } break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 387 |  | 
 | 388 |         // handle input device disconnection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 389 |         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 390 |             if (index < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 391 |                 ALOGW("setDeviceConnectionState() device not connected: %d", device); | 
 | 392 |                 return INVALID_OPERATION; | 
 | 393 |             } | 
| Paul McLean | 5c477aa | 2014-08-20 16:47:57 -0700 | [diff] [blame] | 394 |  | 
 | 395 |             ALOGV("setDeviceConnectionState() disconnecting input device %x", device); | 
 | 396 |  | 
 | 397 |             // Set Disconnect to HALs | 
 | 398 |             AudioParameter param = AudioParameter(address); | 
 | 399 |             param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device); | 
 | 400 |             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString()); | 
 | 401 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 402 |             checkInputsForDevice(device, state, inputs, address); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 403 |             mAvailableInputDevices.remove(devDesc); | 
| Paul McLean | 5c477aa | 2014-08-20 16:47:57 -0700 | [diff] [blame] | 404 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 405 |         } break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 406 |  | 
 | 407 |         default: | 
 | 408 |             ALOGE("setDeviceConnectionState() invalid state: %x", state); | 
 | 409 |             return BAD_VALUE; | 
 | 410 |         } | 
 | 411 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 412 |         closeAllInputs(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 413 |  | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 414 |         if (mPhoneState == AUDIO_MODE_IN_CALL) { | 
 | 415 |             audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/); | 
 | 416 |             updateCallRouting(newDevice); | 
 | 417 |         } | 
 | 418 |  | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 419 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 420 |         return NO_ERROR; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 421 |     } // end if is input device | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 422 |  | 
 | 423 |     ALOGW("setDeviceConnectionState() invalid device: %x", device); | 
 | 424 |     return BAD_VALUE; | 
 | 425 | } | 
 | 426 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 427 | audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 428 |                                                   const char *device_address) | 
 | 429 | { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 430 |     audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 431 |     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
| Eric Laurent | 2222601 | 2014-08-01 17:00:54 -0700 | [diff] [blame] | 432 |     devDesc->mAddress = (device_address == NULL) ? String8("") : String8(device_address); | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 433 |     // handle legacy remote submix case where the address was not always specified | 
 | 434 |     if (deviceDistinguishesOnAddress(device) && (devDesc->mAddress.length() == 0)) { | 
 | 435 |         devDesc->mAddress = String8("0"); | 
 | 436 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 437 |     ssize_t index; | 
 | 438 |     DeviceVector *deviceVector; | 
 | 439 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 440 |     if (audio_is_output_device(device)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 441 |         deviceVector = &mAvailableOutputDevices; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 442 |     } else if (audio_is_input_device(device)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 443 |         deviceVector = &mAvailableInputDevices; | 
 | 444 |     } else { | 
 | 445 |         ALOGW("getDeviceConnectionState() invalid device type %08x", device); | 
 | 446 |         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 447 |     } | 
 | 448 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 449 |     index = deviceVector->indexOf(devDesc); | 
 | 450 |     if (index >= 0) { | 
 | 451 |         return AUDIO_POLICY_DEVICE_STATE_AVAILABLE; | 
 | 452 |     } else { | 
 | 453 |         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
 | 454 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 455 | } | 
 | 456 |  | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 457 | void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs) | 
 | 458 | { | 
 | 459 |     bool createTxPatch = false; | 
 | 460 |     struct audio_patch patch; | 
 | 461 |     patch.num_sources = 1; | 
 | 462 |     patch.num_sinks = 1; | 
 | 463 |     status_t status; | 
 | 464 |     audio_patch_handle_t afPatchHandle; | 
 | 465 |     DeviceVector deviceList; | 
 | 466 |  | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 467 |     audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 468 |     ALOGV("updateCallRouting device rxDevice %08x txDevice %08x", rxDevice, txDevice); | 
 | 469 |  | 
 | 470 |     // release existing RX patch if any | 
 | 471 |     if (mCallRxPatch != 0) { | 
 | 472 |         mpClientInterface->releaseAudioPatch(mCallRxPatch->mAfPatchHandle, 0); | 
 | 473 |         mCallRxPatch.clear(); | 
 | 474 |     } | 
 | 475 |     // release TX patch if any | 
 | 476 |     if (mCallTxPatch != 0) { | 
 | 477 |         mpClientInterface->releaseAudioPatch(mCallTxPatch->mAfPatchHandle, 0); | 
 | 478 |         mCallTxPatch.clear(); | 
 | 479 |     } | 
 | 480 |  | 
 | 481 |     // If the RX device is on the primary HW module, then use legacy routing method for voice calls | 
 | 482 |     // via setOutputDevice() on primary output. | 
 | 483 |     // Otherwise, create two audio patches for TX and RX path. | 
 | 484 |     if (availablePrimaryOutputDevices() & rxDevice) { | 
 | 485 |         setOutputDevice(mPrimaryOutput, rxDevice, true, delayMs); | 
 | 486 |         // If the TX device is also on the primary HW module, setOutputDevice() will take care | 
 | 487 |         // of it due to legacy implementation. If not, create a patch. | 
 | 488 |         if ((availablePrimaryInputDevices() & txDevice & ~AUDIO_DEVICE_BIT_IN) | 
 | 489 |                 == AUDIO_DEVICE_NONE) { | 
 | 490 |             createTxPatch = true; | 
 | 491 |         } | 
 | 492 |     } else { | 
 | 493 |         // create RX path audio patch | 
 | 494 |         deviceList = mAvailableOutputDevices.getDevicesFromType(rxDevice); | 
 | 495 |         ALOG_ASSERT(!deviceList.isEmpty(), | 
 | 496 |                     "updateCallRouting() selected device not in output device list"); | 
 | 497 |         sp<DeviceDescriptor> rxSinkDeviceDesc = deviceList.itemAt(0); | 
 | 498 |         deviceList = mAvailableInputDevices.getDevicesFromType(AUDIO_DEVICE_IN_TELEPHONY_RX); | 
 | 499 |         ALOG_ASSERT(!deviceList.isEmpty(), | 
 | 500 |                     "updateCallRouting() no telephony RX device"); | 
 | 501 |         sp<DeviceDescriptor> rxSourceDeviceDesc = deviceList.itemAt(0); | 
 | 502 |  | 
 | 503 |         rxSourceDeviceDesc->toAudioPortConfig(&patch.sources[0]); | 
 | 504 |         rxSinkDeviceDesc->toAudioPortConfig(&patch.sinks[0]); | 
 | 505 |  | 
 | 506 |         // request to reuse existing output stream if one is already opened to reach the RX device | 
 | 507 |         SortedVector<audio_io_handle_t> outputs = | 
 | 508 |                                 getOutputsForDevice(rxDevice, mOutputs); | 
| Eric Laurent | 8838a38 | 2014-09-08 16:44:28 -0700 | [diff] [blame] | 509 |         audio_io_handle_t output = selectOutput(outputs, | 
 | 510 |                                                 AUDIO_OUTPUT_FLAG_NONE, | 
 | 511 |                                                 AUDIO_FORMAT_INVALID); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 512 |         if (output != AUDIO_IO_HANDLE_NONE) { | 
 | 513 |             sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
 | 514 |             ALOG_ASSERT(!outputDesc->isDuplicated(), | 
 | 515 |                         "updateCallRouting() RX device output is duplicated"); | 
 | 516 |             outputDesc->toAudioPortConfig(&patch.sources[1]); | 
 | 517 |             patch.num_sources = 2; | 
 | 518 |         } | 
 | 519 |  | 
 | 520 |         afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 521 |         status = mpClientInterface->createAudioPatch(&patch, &afPatchHandle, 0); | 
 | 522 |         ALOGW_IF(status != NO_ERROR, "updateCallRouting() error %d creating RX audio patch", | 
 | 523 |                                                status); | 
 | 524 |         if (status == NO_ERROR) { | 
 | 525 |             mCallRxPatch = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 526 |                                        &patch, mUidCached); | 
 | 527 |             mCallRxPatch->mAfPatchHandle = afPatchHandle; | 
 | 528 |             mCallRxPatch->mUid = mUidCached; | 
 | 529 |         } | 
 | 530 |         createTxPatch = true; | 
 | 531 |     } | 
 | 532 |     if (createTxPatch) { | 
 | 533 |  | 
 | 534 |         struct audio_patch patch; | 
 | 535 |         patch.num_sources = 1; | 
 | 536 |         patch.num_sinks = 1; | 
 | 537 |         deviceList = mAvailableInputDevices.getDevicesFromType(txDevice); | 
 | 538 |         ALOG_ASSERT(!deviceList.isEmpty(), | 
 | 539 |                     "updateCallRouting() selected device not in input device list"); | 
 | 540 |         sp<DeviceDescriptor> txSourceDeviceDesc = deviceList.itemAt(0); | 
 | 541 |         txSourceDeviceDesc->toAudioPortConfig(&patch.sources[0]); | 
 | 542 |         deviceList = mAvailableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_TELEPHONY_TX); | 
 | 543 |         ALOG_ASSERT(!deviceList.isEmpty(), | 
 | 544 |                     "updateCallRouting() no telephony TX device"); | 
 | 545 |         sp<DeviceDescriptor> txSinkDeviceDesc = deviceList.itemAt(0); | 
 | 546 |         txSinkDeviceDesc->toAudioPortConfig(&patch.sinks[0]); | 
 | 547 |  | 
 | 548 |         SortedVector<audio_io_handle_t> outputs = | 
 | 549 |                                 getOutputsForDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX, mOutputs); | 
| Eric Laurent | 8838a38 | 2014-09-08 16:44:28 -0700 | [diff] [blame] | 550 |         audio_io_handle_t output = selectOutput(outputs, | 
 | 551 |                                                 AUDIO_OUTPUT_FLAG_NONE, | 
 | 552 |                                                 AUDIO_FORMAT_INVALID); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 553 |         // request to reuse existing output stream if one is already opened to reach the TX | 
 | 554 |         // path output device | 
 | 555 |         if (output != AUDIO_IO_HANDLE_NONE) { | 
 | 556 |             sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
 | 557 |             ALOG_ASSERT(!outputDesc->isDuplicated(), | 
 | 558 |                         "updateCallRouting() RX device output is duplicated"); | 
 | 559 |             outputDesc->toAudioPortConfig(&patch.sources[1]); | 
 | 560 |             patch.num_sources = 2; | 
 | 561 |         } | 
 | 562 |  | 
 | 563 |         afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 564 |         status = mpClientInterface->createAudioPatch(&patch, &afPatchHandle, 0); | 
 | 565 |         ALOGW_IF(status != NO_ERROR, "setPhoneState() error %d creating TX audio patch", | 
 | 566 |                                                status); | 
 | 567 |         if (status == NO_ERROR) { | 
 | 568 |             mCallTxPatch = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 569 |                                        &patch, mUidCached); | 
 | 570 |             mCallTxPatch->mAfPatchHandle = afPatchHandle; | 
 | 571 |             mCallTxPatch->mUid = mUidCached; | 
 | 572 |         } | 
 | 573 |     } | 
 | 574 | } | 
 | 575 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 576 | void AudioPolicyManager::setPhoneState(audio_mode_t state) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 577 | { | 
 | 578 |     ALOGV("setPhoneState() state %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 579 |     if (state < 0 || state >= AUDIO_MODE_CNT) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 580 |         ALOGW("setPhoneState() invalid state %d", state); | 
 | 581 |         return; | 
 | 582 |     } | 
 | 583 |  | 
 | 584 |     if (state == mPhoneState ) { | 
 | 585 |         ALOGW("setPhoneState() setting same state %d", state); | 
 | 586 |         return; | 
 | 587 |     } | 
 | 588 |  | 
 | 589 |     // if leaving call state, handle special case of active streams | 
 | 590 |     // pertaining to sonification strategy see handleIncallSonification() | 
 | 591 |     if (isInCall()) { | 
 | 592 |         ALOGV("setPhoneState() in call state management: new state is %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 593 |         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 594 |             if (stream == AUDIO_STREAM_PATCH) { | 
 | 595 |                 continue; | 
 | 596 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 597 |             handleIncallSonification((audio_stream_type_t)stream, false, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 598 |         } | 
| Eric Laurent | 2cbe89a | 2014-12-19 11:49:08 -0800 | [diff] [blame] | 599 |  | 
 | 600 |         // force reevaluating accessibility routing when call starts | 
 | 601 |         mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 602 |     } | 
 | 603 |  | 
 | 604 |     // store previous phone state for management of sonification strategy below | 
 | 605 |     int oldState = mPhoneState; | 
 | 606 |     mPhoneState = state; | 
 | 607 |     bool force = false; | 
 | 608 |  | 
 | 609 |     // are we entering or starting a call | 
 | 610 |     if (!isStateInCall(oldState) && isStateInCall(state)) { | 
 | 611 |         ALOGV("  Entering call in setPhoneState()"); | 
 | 612 |         // force routing command to audio hardware when starting a call | 
 | 613 |         // even if no device change is needed | 
 | 614 |         force = true; | 
 | 615 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 616 |             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = | 
 | 617 |                     sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]; | 
 | 618 |         } | 
 | 619 |     } else if (isStateInCall(oldState) && !isStateInCall(state)) { | 
 | 620 |         ALOGV("  Exiting call in setPhoneState()"); | 
 | 621 |         // force routing command to audio hardware when exiting a call | 
 | 622 |         // even if no device change is needed | 
 | 623 |         force = true; | 
 | 624 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 625 |             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = | 
 | 626 |                     sVolumeProfiles[AUDIO_STREAM_DTMF][j]; | 
 | 627 |         } | 
 | 628 |     } else if (isStateInCall(state) && (state != oldState)) { | 
 | 629 |         ALOGV("  Switching between telephony and VoIP in setPhoneState()"); | 
 | 630 |         // force routing command to audio hardware when switching between telephony and VoIP | 
 | 631 |         // even if no device change is needed | 
 | 632 |         force = true; | 
 | 633 |     } | 
 | 634 |  | 
 | 635 |     // check for device and output changes triggered by new phone state | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 636 |     checkA2dpSuspend(); | 
 | 637 |     checkOutputForAllStrategies(); | 
 | 638 |     updateDevicesAndOutputs(); | 
 | 639 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 640 |     sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 641 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 642 |     int delayMs = 0; | 
 | 643 |     if (isStateInCall(state)) { | 
 | 644 |         nsecs_t sysTime = systemTime(); | 
 | 645 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 646 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 647 |             // mute media and sonification strategies and delay device switch by the largest | 
 | 648 |             // latency of any output where either strategy is active. | 
 | 649 |             // This avoid sending the ring tone or music tail into the earpiece or headset. | 
 | 650 |             if ((desc->isStrategyActive(STRATEGY_MEDIA, | 
 | 651 |                                      SONIFICATION_HEADSET_MUSIC_DELAY, | 
 | 652 |                                      sysTime) || | 
 | 653 |                     desc->isStrategyActive(STRATEGY_SONIFICATION, | 
 | 654 |                                          SONIFICATION_HEADSET_MUSIC_DELAY, | 
 | 655 |                                          sysTime)) && | 
 | 656 |                     (delayMs < (int)desc->mLatency*2)) { | 
 | 657 |                 delayMs = desc->mLatency*2; | 
 | 658 |             } | 
 | 659 |             setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); | 
 | 660 |             setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, | 
 | 661 |                 getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); | 
 | 662 |             setStrategyMute(STRATEGY_SONIFICATION, true, mOutputs.keyAt(i)); | 
 | 663 |             setStrategyMute(STRATEGY_SONIFICATION, false, mOutputs.keyAt(i), MUTE_TIME_MS, | 
 | 664 |                 getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/)); | 
 | 665 |         } | 
 | 666 |     } | 
 | 667 |  | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 668 |     // Note that despite the fact that getNewOutputDevice() is called on the primary output, | 
 | 669 |     // the device returned is not necessarily reachable via this output | 
 | 670 |     audio_devices_t rxDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/); | 
 | 671 |     // force routing command to audio hardware when ending call | 
 | 672 |     // even if no device change is needed | 
 | 673 |     if (isStateInCall(oldState) && rxDevice == AUDIO_DEVICE_NONE) { | 
 | 674 |         rxDevice = hwOutputDesc->device(); | 
 | 675 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 676 |  | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 677 |     if (state == AUDIO_MODE_IN_CALL) { | 
 | 678 |         updateCallRouting(rxDevice, delayMs); | 
 | 679 |     } else if (oldState == AUDIO_MODE_IN_CALL) { | 
 | 680 |         if (mCallRxPatch != 0) { | 
 | 681 |             mpClientInterface->releaseAudioPatch(mCallRxPatch->mAfPatchHandle, 0); | 
 | 682 |             mCallRxPatch.clear(); | 
 | 683 |         } | 
 | 684 |         if (mCallTxPatch != 0) { | 
 | 685 |             mpClientInterface->releaseAudioPatch(mCallTxPatch->mAfPatchHandle, 0); | 
 | 686 |             mCallTxPatch.clear(); | 
 | 687 |         } | 
 | 688 |         setOutputDevice(mPrimaryOutput, rxDevice, force, 0); | 
 | 689 |     } else { | 
 | 690 |         setOutputDevice(mPrimaryOutput, rxDevice, force, 0); | 
 | 691 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 692 |     // if entering in call state, handle special case of active streams | 
 | 693 |     // pertaining to sonification strategy see handleIncallSonification() | 
 | 694 |     if (isStateInCall(state)) { | 
 | 695 |         ALOGV("setPhoneState() in call state management: new state is %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 696 |         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 697 |             if (stream == AUDIO_STREAM_PATCH) { | 
 | 698 |                 continue; | 
 | 699 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 700 |             handleIncallSonification((audio_stream_type_t)stream, true, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 701 |         } | 
 | 702 |     } | 
 | 703 |  | 
 | 704 |     // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 705 |     if (state == AUDIO_MODE_RINGTONE && | 
 | 706 |         isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 707 |         mLimitRingtoneVolume = true; | 
 | 708 |     } else { | 
 | 709 |         mLimitRingtoneVolume = false; | 
 | 710 |     } | 
 | 711 | } | 
 | 712 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 713 | void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 714 |                                          audio_policy_forced_cfg_t config) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 715 | { | 
 | 716 |     ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState); | 
 | 717 |  | 
 | 718 |     bool forceVolumeReeval = false; | 
 | 719 |     switch(usage) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 720 |     case AUDIO_POLICY_FORCE_FOR_COMMUNICATION: | 
 | 721 |         if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO && | 
 | 722 |             config != AUDIO_POLICY_FORCE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 723 |             ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config); | 
 | 724 |             return; | 
 | 725 |         } | 
 | 726 |         forceVolumeReeval = true; | 
 | 727 |         mForceUse[usage] = config; | 
 | 728 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 729 |     case AUDIO_POLICY_FORCE_FOR_MEDIA: | 
 | 730 |         if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP && | 
 | 731 |             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 732 |             config != AUDIO_POLICY_FORCE_ANALOG_DOCK && | 
 | 733 |             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE && | 
| Hochi Huang | 327cb70 | 2014-09-21 09:47:31 +0800 | [diff] [blame] | 734 |             config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 735 |             ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config); | 
 | 736 |             return; | 
 | 737 |         } | 
 | 738 |         mForceUse[usage] = config; | 
 | 739 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 740 |     case AUDIO_POLICY_FORCE_FOR_RECORD: | 
 | 741 |         if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 742 |             config != AUDIO_POLICY_FORCE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 743 |             ALOGW("setForceUse() invalid config %d for FOR_RECORD", config); | 
 | 744 |             return; | 
 | 745 |         } | 
 | 746 |         mForceUse[usage] = config; | 
 | 747 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 748 |     case AUDIO_POLICY_FORCE_FOR_DOCK: | 
 | 749 |         if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK && | 
 | 750 |             config != AUDIO_POLICY_FORCE_BT_DESK_DOCK && | 
 | 751 |             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 752 |             config != AUDIO_POLICY_FORCE_ANALOG_DOCK && | 
 | 753 |             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 754 |             ALOGW("setForceUse() invalid config %d for FOR_DOCK", config); | 
 | 755 |         } | 
 | 756 |         forceVolumeReeval = true; | 
 | 757 |         mForceUse[usage] = config; | 
 | 758 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 759 |     case AUDIO_POLICY_FORCE_FOR_SYSTEM: | 
 | 760 |         if (config != AUDIO_POLICY_FORCE_NONE && | 
 | 761 |             config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 762 |             ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config); | 
 | 763 |         } | 
 | 764 |         forceVolumeReeval = true; | 
 | 765 |         mForceUse[usage] = config; | 
 | 766 |         break; | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 767 |     case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO: | 
 | 768 |         if (config != AUDIO_POLICY_FORCE_NONE && | 
 | 769 |             config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) { | 
 | 770 |             ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config); | 
 | 771 |         } | 
 | 772 |         mForceUse[usage] = config; | 
 | 773 |         break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 774 |     default: | 
 | 775 |         ALOGW("setForceUse() invalid usage %d", usage); | 
 | 776 |         break; | 
 | 777 |     } | 
 | 778 |  | 
 | 779 |     // check for device and output changes triggered by new force usage | 
 | 780 |     checkA2dpSuspend(); | 
 | 781 |     checkOutputForAllStrategies(); | 
 | 782 |     updateDevicesAndOutputs(); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 783 |     if (mPhoneState == AUDIO_MODE_IN_CALL) { | 
 | 784 |         audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/); | 
 | 785 |         updateCallRouting(newDevice); | 
 | 786 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 787 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 788 |         audio_io_handle_t output = mOutputs.keyAt(i); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 789 |         audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 790 |         if ((mPhoneState != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) { | 
 | 791 |             setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE)); | 
 | 792 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 793 |         if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) { | 
 | 794 |             applyStreamVolumes(output, newDevice, 0, true); | 
 | 795 |         } | 
 | 796 |     } | 
 | 797 |  | 
 | 798 |     audio_io_handle_t activeInput = getActiveInput(); | 
 | 799 |     if (activeInput != 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 800 |         setInputDevice(activeInput, getNewInputDevice(activeInput)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 801 |     } | 
 | 802 |  | 
 | 803 | } | 
 | 804 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 805 | audio_policy_forced_cfg_t AudioPolicyManager::getForceUse(audio_policy_force_use_t usage) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 806 | { | 
 | 807 |     return mForceUse[usage]; | 
 | 808 | } | 
 | 809 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 810 | void AudioPolicyManager::setSystemProperty(const char* property, const char* value) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 811 | { | 
 | 812 |     ALOGV("setSystemProperty() property %s, value %s", property, value); | 
 | 813 | } | 
 | 814 |  | 
 | 815 | // Find a direct output profile compatible with the parameters passed, even if the input flags do | 
 | 816 | // not explicitly request a direct output | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 817 | sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getProfileForDirectOutput( | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 818 |                                                                audio_devices_t device, | 
 | 819 |                                                                uint32_t samplingRate, | 
 | 820 |                                                                audio_format_t format, | 
 | 821 |                                                                audio_channel_mask_t channelMask, | 
 | 822 |                                                                audio_output_flags_t flags) | 
 | 823 | { | 
 | 824 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 825 |         if (mHwModules[i]->mHandle == 0) { | 
 | 826 |             continue; | 
 | 827 |         } | 
 | 828 |         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 829 |             sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 830 |             bool found = profile->isCompatibleProfile(device, String8(""), samplingRate, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 831 |                     NULL /*updatedSamplingRate*/, format, channelMask, | 
 | 832 |                     flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ? | 
 | 833 |                         AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_DIRECT); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 834 |             if (found && (mAvailableOutputDevices.types() & profile->mSupportedDevices.types())) { | 
 | 835 |                 return profile; | 
 | 836 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 837 |         } | 
 | 838 |     } | 
 | 839 |     return 0; | 
 | 840 | } | 
 | 841 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 842 | audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 843 |                                     uint32_t samplingRate, | 
 | 844 |                                     audio_format_t format, | 
 | 845 |                                     audio_channel_mask_t channelMask, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 846 |                                     audio_output_flags_t flags, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 847 |                                     const audio_offload_info_t *offloadInfo) | 
 | 848 | { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 849 |     routing_strategy strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 850 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 851 |     ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x", | 
 | 852 |           device, stream, samplingRate, format, channelMask, flags); | 
 | 853 |  | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 854 |     return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE, | 
 | 855 |                               stream, samplingRate,format, channelMask, | 
 | 856 |                               flags, offloadInfo); | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 857 | } | 
 | 858 |  | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 859 | status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, | 
 | 860 |                                               audio_io_handle_t *output, | 
 | 861 |                                               audio_session_t session, | 
 | 862 |                                               audio_stream_type_t *stream, | 
 | 863 |                                               uint32_t samplingRate, | 
 | 864 |                                               audio_format_t format, | 
 | 865 |                                               audio_channel_mask_t channelMask, | 
 | 866 |                                               audio_output_flags_t flags, | 
 | 867 |                                               const audio_offload_info_t *offloadInfo) | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 868 | { | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 869 |     audio_attributes_t attributes; | 
 | 870 |     if (attr != NULL) { | 
 | 871 |         if (!isValidAttributes(attr)) { | 
 | 872 |             ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]", | 
 | 873 |                   attr->usage, attr->content_type, attr->flags, | 
 | 874 |                   attr->tags); | 
 | 875 |             return BAD_VALUE; | 
 | 876 |         } | 
 | 877 |         attributes = *attr; | 
 | 878 |     } else { | 
 | 879 |         if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) { | 
 | 880 |             ALOGE("getOutputForAttr():  invalid stream type"); | 
 | 881 |             return BAD_VALUE; | 
 | 882 |         } | 
 | 883 |         stream_type_to_audio_attributes(*stream, &attributes); | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 884 |     } | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 885 |  | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 886 |     for (size_t i = 0; i < mPolicyMixes.size(); i++) { | 
 | 887 |         sp<AudioOutputDescriptor> desc; | 
 | 888 |         if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_PLAYERS) { | 
 | 889 |             for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) { | 
 | 890 |                 if ((RULE_MATCH_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule && | 
 | 891 |                         mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage == attributes.usage) || | 
 | 892 |                     (RULE_EXCLUDE_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule && | 
 | 893 |                         mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage != attributes.usage)) { | 
 | 894 |                     desc = mPolicyMixes[i]->mOutput; | 
 | 895 |                     break; | 
 | 896 |                 } | 
 | 897 |                 if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && | 
 | 898 |                         strncmp(attributes.tags + strlen("addr="), | 
 | 899 |                                 mPolicyMixes[i]->mMix.mRegistrationId.string(), | 
 | 900 |                                 AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { | 
 | 901 |                     desc = mPolicyMixes[i]->mOutput; | 
 | 902 |                     break; | 
 | 903 |                 } | 
 | 904 |             } | 
 | 905 |         } else if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_RECORDERS) { | 
 | 906 |             if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE && | 
 | 907 |                     strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 && | 
 | 908 |                     strncmp(attributes.tags + strlen("addr="), | 
 | 909 |                             mPolicyMixes[i]->mMix.mRegistrationId.string(), | 
 | 910 |                             AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) { | 
 | 911 |                 desc = mPolicyMixes[i]->mOutput; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 912 |             } | 
 | 913 |         } | 
 | 914 |         if (desc != 0) { | 
 | 915 |             if (!audio_is_linear_pcm(format)) { | 
 | 916 |                 return BAD_VALUE; | 
 | 917 |             } | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 918 |             desc->mPolicyMix = &mPolicyMixes[i]->mMix; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 919 |             *stream = streamTypefromAttributesInt(&attributes); | 
 | 920 |             *output = desc->mIoHandle; | 
 | 921 |             ALOGV("getOutputForAttr() returns output %d", *output); | 
 | 922 |             return NO_ERROR; | 
 | 923 |         } | 
 | 924 |     } | 
 | 925 |     if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) { | 
 | 926 |         ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE"); | 
 | 927 |         return BAD_VALUE; | 
 | 928 |     } | 
 | 929 |  | 
| Eric Laurent | 93c3d41 | 2014-08-01 14:48:35 -0700 | [diff] [blame] | 930 |     ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x", | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 931 |             attributes.usage, attributes.content_type, attributes.tags, attributes.flags); | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 932 |  | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 933 |     routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes); | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 934 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
| Eric Laurent | 93c3d41 | 2014-08-01 14:48:35 -0700 | [diff] [blame] | 935 |  | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 936 |     if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { | 
| Eric Laurent | 93c3d41 | 2014-08-01 14:48:35 -0700 | [diff] [blame] | 937 |         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC); | 
 | 938 |     } | 
 | 939 |  | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 940 |     ALOGV("getOutputForAttr() device 0x%x, samplingRate %d, format %x, channelMask %x, flags %x", | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 941 |           device, samplingRate, format, channelMask, flags); | 
 | 942 |  | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 943 |     *stream = streamTypefromAttributesInt(&attributes); | 
 | 944 |     *output = getOutputForDevice(device, session, *stream, | 
 | 945 |                                  samplingRate, format, channelMask, | 
 | 946 |                                  flags, offloadInfo); | 
 | 947 |     if (*output == AUDIO_IO_HANDLE_NONE) { | 
 | 948 |         return INVALID_OPERATION; | 
 | 949 |     } | 
 | 950 |     return NO_ERROR; | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 951 | } | 
 | 952 |  | 
 | 953 | audio_io_handle_t AudioPolicyManager::getOutputForDevice( | 
 | 954 |         audio_devices_t device, | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 955 |         audio_session_t session __unused, | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 956 |         audio_stream_type_t stream, | 
 | 957 |         uint32_t samplingRate, | 
 | 958 |         audio_format_t format, | 
 | 959 |         audio_channel_mask_t channelMask, | 
 | 960 |         audio_output_flags_t flags, | 
 | 961 |         const audio_offload_info_t *offloadInfo) | 
 | 962 | { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 963 |     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 964 |     uint32_t latency = 0; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 965 |     status_t status; | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 966 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 967 | #ifdef AUDIO_POLICY_TEST | 
 | 968 |     if (mCurOutput != 0) { | 
 | 969 |         ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d", | 
 | 970 |                 mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput); | 
 | 971 |  | 
 | 972 |         if (mTestOutputs[mCurOutput] == 0) { | 
 | 973 |             ALOGV("getOutput() opening test output"); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 974 |             sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 975 |             outputDesc->mDevice = mTestDevice; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 976 |             outputDesc->mLatency = mTestLatencyMs; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 977 |             outputDesc->mFlags = | 
 | 978 |                     (audio_output_flags_t)(mDirectOutput ? AUDIO_OUTPUT_FLAG_DIRECT : 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 979 |             outputDesc->mRefCount[stream] = 0; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 980 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 981 |             config.sample_rate = mTestSamplingRate; | 
 | 982 |             config.channel_mask = mTestChannels; | 
 | 983 |             config.format = mTestFormat; | 
| Phil Burk | 77cce80 | 2014-08-04 16:18:15 -0700 | [diff] [blame] | 984 |             if (offloadInfo != NULL) { | 
 | 985 |                 config.offload_info = *offloadInfo; | 
 | 986 |             } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 987 |             status = mpClientInterface->openOutput(0, | 
 | 988 |                                                   &mTestOutputs[mCurOutput], | 
 | 989 |                                                   &config, | 
 | 990 |                                                   &outputDesc->mDevice, | 
 | 991 |                                                   String8(""), | 
 | 992 |                                                   &outputDesc->mLatency, | 
 | 993 |                                                   outputDesc->mFlags); | 
 | 994 |             if (status == NO_ERROR) { | 
 | 995 |                 outputDesc->mSamplingRate = config.sample_rate; | 
 | 996 |                 outputDesc->mFormat = config.format; | 
 | 997 |                 outputDesc->mChannelMask = config.channel_mask; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 998 |                 AudioParameter outputCmd = AudioParameter(); | 
 | 999 |                 outputCmd.addInt(String8("set_id"),mCurOutput); | 
 | 1000 |                 mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString()); | 
 | 1001 |                 addOutput(mTestOutputs[mCurOutput], outputDesc); | 
 | 1002 |             } | 
 | 1003 |         } | 
 | 1004 |         return mTestOutputs[mCurOutput]; | 
 | 1005 |     } | 
 | 1006 | #endif //AUDIO_POLICY_TEST | 
 | 1007 |  | 
 | 1008 |     // open a direct output if required by specified parameters | 
 | 1009 |     //force direct flag if offload flag is set: offloading implies a direct output stream | 
 | 1010 |     // and all common behaviors are driven by checking only the direct flag | 
 | 1011 |     // this should normally be set appropriately in the policy configuration file | 
 | 1012 |     if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1013 |         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1014 |     } | 
| Eric Laurent | 93c3d41 | 2014-08-01 14:48:35 -0700 | [diff] [blame] | 1015 |     if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) { | 
 | 1016 |         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT); | 
 | 1017 |     } | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 1018 |     // only allow deep buffering for music stream type | 
 | 1019 |     if (stream != AUDIO_STREAM_MUSIC) { | 
 | 1020 |         flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER); | 
 | 1021 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1022 |  | 
| Eric Laurent | b732cf5 | 2014-09-24 19:08:21 -0700 | [diff] [blame] | 1023 |     sp<IOProfile> profile; | 
 | 1024 |  | 
 | 1025 |     // skip direct output selection if the request can obviously be attached to a mixed output | 
| Eric Laurent | c260784 | 2014-09-29 09:43:03 -0700 | [diff] [blame] | 1026 |     // and not explicitly requested | 
 | 1027 |     if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) && | 
 | 1028 |             audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE && | 
| Eric Laurent | b732cf5 | 2014-09-24 19:08:21 -0700 | [diff] [blame] | 1029 |             audio_channel_count_from_out_mask(channelMask) <= 2) { | 
 | 1030 |         goto non_direct_output; | 
 | 1031 |     } | 
 | 1032 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1033 |     // Do not allow offloading if one non offloadable effect is enabled. This prevents from | 
 | 1034 |     // creating an offloaded track and tearing it down immediately after start when audioflinger | 
 | 1035 |     // detects there is an active non offloadable effect. | 
 | 1036 |     // FIXME: We should check the audio session here but we do not have it in this context. | 
 | 1037 |     // This may prevent offloading in rare situations where effects are left active by apps | 
 | 1038 |     // in the background. | 
| Eric Laurent | b732cf5 | 2014-09-24 19:08:21 -0700 | [diff] [blame] | 1039 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1040 |     if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || | 
 | 1041 |             !isNonOffloadableEffectEnabled()) { | 
 | 1042 |         profile = getProfileForDirectOutput(device, | 
 | 1043 |                                            samplingRate, | 
 | 1044 |                                            format, | 
 | 1045 |                                            channelMask, | 
 | 1046 |                                            (audio_output_flags_t)flags); | 
 | 1047 |     } | 
 | 1048 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1049 |     if (profile != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1050 |         sp<AudioOutputDescriptor> outputDesc = NULL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1051 |  | 
 | 1052 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1053 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1054 |             if (!desc->isDuplicated() && (profile == desc->mProfile)) { | 
 | 1055 |                 outputDesc = desc; | 
 | 1056 |                 // reuse direct output if currently open and configured with same parameters | 
 | 1057 |                 if ((samplingRate == outputDesc->mSamplingRate) && | 
 | 1058 |                         (format == outputDesc->mFormat) && | 
 | 1059 |                         (channelMask == outputDesc->mChannelMask)) { | 
 | 1060 |                     outputDesc->mDirectOpenCount++; | 
 | 1061 |                     ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i)); | 
 | 1062 |                     return mOutputs.keyAt(i); | 
 | 1063 |                 } | 
 | 1064 |             } | 
 | 1065 |         } | 
 | 1066 |         // close direct output if currently open and configured with different parameters | 
 | 1067 |         if (outputDesc != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1068 |             closeOutput(outputDesc->mIoHandle); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1069 |         } | 
 | 1070 |         outputDesc = new AudioOutputDescriptor(profile); | 
 | 1071 |         outputDesc->mDevice = device; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1072 |         outputDesc->mLatency = 0; | 
 | 1073 |         outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1074 |         audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 1075 |         config.sample_rate = samplingRate; | 
 | 1076 |         config.channel_mask = channelMask; | 
 | 1077 |         config.format = format; | 
| Phil Burk | 77cce80 | 2014-08-04 16:18:15 -0700 | [diff] [blame] | 1078 |         if (offloadInfo != NULL) { | 
 | 1079 |             config.offload_info = *offloadInfo; | 
 | 1080 |         } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1081 |         status = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 1082 |                                                &output, | 
 | 1083 |                                                &config, | 
 | 1084 |                                                &outputDesc->mDevice, | 
 | 1085 |                                                String8(""), | 
 | 1086 |                                                &outputDesc->mLatency, | 
 | 1087 |                                                outputDesc->mFlags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1088 |  | 
 | 1089 |         // only accept an output with the requested parameters | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1090 |         if (status != NO_ERROR || | 
 | 1091 |             (samplingRate != 0 && samplingRate != config.sample_rate) || | 
 | 1092 |             (format != AUDIO_FORMAT_DEFAULT && format != config.format) || | 
 | 1093 |             (channelMask != 0 && channelMask != config.channel_mask)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1094 |             ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d," | 
 | 1095 |                     "format %d %d, channelMask %04x %04x", output, samplingRate, | 
 | 1096 |                     outputDesc->mSamplingRate, format, outputDesc->mFormat, channelMask, | 
 | 1097 |                     outputDesc->mChannelMask); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1098 |             if (output != AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1099 |                 mpClientInterface->closeOutput(output); | 
 | 1100 |             } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1101 |             return AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1102 |         } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1103 |         outputDesc->mSamplingRate = config.sample_rate; | 
 | 1104 |         outputDesc->mChannelMask = config.channel_mask; | 
 | 1105 |         outputDesc->mFormat = config.format; | 
 | 1106 |         outputDesc->mRefCount[stream] = 0; | 
 | 1107 |         outputDesc->mStopTime[stream] = 0; | 
 | 1108 |         outputDesc->mDirectOpenCount = 1; | 
 | 1109 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1110 |         audio_io_handle_t srcOutput = getOutputForEffect(); | 
 | 1111 |         addOutput(output, outputDesc); | 
 | 1112 |         audio_io_handle_t dstOutput = getOutputForEffect(); | 
 | 1113 |         if (dstOutput == output) { | 
 | 1114 |             mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput); | 
 | 1115 |         } | 
 | 1116 |         mPreviousOutputs = mOutputs; | 
 | 1117 |         ALOGV("getOutput() returns new direct output %d", output); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1118 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1119 |         return output; | 
 | 1120 |     } | 
 | 1121 |  | 
| Eric Laurent | b732cf5 | 2014-09-24 19:08:21 -0700 | [diff] [blame] | 1122 | non_direct_output: | 
 | 1123 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1124 |     // ignoring channel mask due to downmix capability in mixer | 
 | 1125 |  | 
 | 1126 |     // open a non direct output | 
 | 1127 |  | 
 | 1128 |     // for non direct outputs, only PCM is supported | 
 | 1129 |     if (audio_is_linear_pcm(format)) { | 
 | 1130 |         // get which output is suitable for the specified stream. The actual | 
 | 1131 |         // routing change will happen when startOutput() will be called | 
 | 1132 |         SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); | 
 | 1133 |  | 
| Eric Laurent | 8838a38 | 2014-09-08 16:44:28 -0700 | [diff] [blame] | 1134 |         // at this stage we should ignore the DIRECT flag as no direct output could be found earlier | 
 | 1135 |         flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT); | 
 | 1136 |         output = selectOutput(outputs, flags, format); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1137 |     } | 
 | 1138 |     ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d," | 
 | 1139 |             "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags); | 
 | 1140 |  | 
 | 1141 |     ALOGV("getOutput() returns output %d", output); | 
 | 1142 |  | 
 | 1143 |     return output; | 
 | 1144 | } | 
 | 1145 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1146 | audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs, | 
| Eric Laurent | 8838a38 | 2014-09-08 16:44:28 -0700 | [diff] [blame] | 1147 |                                                        audio_output_flags_t flags, | 
 | 1148 |                                                        audio_format_t format) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1149 | { | 
 | 1150 |     // select one output among several that provide a path to a particular device or set of | 
 | 1151 |     // devices (the list was previously build by getOutputsForDevice()). | 
 | 1152 |     // The priority is as follows: | 
 | 1153 |     // 1: the output with the highest number of requested policy flags | 
 | 1154 |     // 2: the primary output | 
 | 1155 |     // 3: the first output in the list | 
 | 1156 |  | 
 | 1157 |     if (outputs.size() == 0) { | 
 | 1158 |         return 0; | 
 | 1159 |     } | 
 | 1160 |     if (outputs.size() == 1) { | 
 | 1161 |         return outputs[0]; | 
 | 1162 |     } | 
 | 1163 |  | 
 | 1164 |     int maxCommonFlags = 0; | 
 | 1165 |     audio_io_handle_t outputFlags = 0; | 
 | 1166 |     audio_io_handle_t outputPrimary = 0; | 
 | 1167 |  | 
 | 1168 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1169 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1170 |         if (!outputDesc->isDuplicated()) { | 
| Eric Laurent | 8838a38 | 2014-09-08 16:44:28 -0700 | [diff] [blame] | 1171 |             // if a valid format is specified, skip output if not compatible | 
 | 1172 |             if (format != AUDIO_FORMAT_INVALID) { | 
 | 1173 |                 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { | 
 | 1174 |                     if (format != outputDesc->mFormat) { | 
 | 1175 |                         continue; | 
 | 1176 |                     } | 
 | 1177 |                 } else if (!audio_is_linear_pcm(format)) { | 
 | 1178 |                     continue; | 
 | 1179 |                 } | 
 | 1180 |             } | 
 | 1181 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1182 |             int commonFlags = popcount(outputDesc->mProfile->mFlags & flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1183 |             if (commonFlags > maxCommonFlags) { | 
 | 1184 |                 outputFlags = outputs[i]; | 
 | 1185 |                 maxCommonFlags = commonFlags; | 
 | 1186 |                 ALOGV("selectOutput() commonFlags for output %d, %04x", outputs[i], commonFlags); | 
 | 1187 |             } | 
 | 1188 |             if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { | 
 | 1189 |                 outputPrimary = outputs[i]; | 
 | 1190 |             } | 
 | 1191 |         } | 
 | 1192 |     } | 
 | 1193 |  | 
 | 1194 |     if (outputFlags != 0) { | 
 | 1195 |         return outputFlags; | 
 | 1196 |     } | 
 | 1197 |     if (outputPrimary != 0) { | 
 | 1198 |         return outputPrimary; | 
 | 1199 |     } | 
 | 1200 |  | 
 | 1201 |     return outputs[0]; | 
 | 1202 | } | 
 | 1203 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1204 | status_t AudioPolicyManager::startOutput(audio_io_handle_t output, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1205 |                                              audio_stream_type_t stream, | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 1206 |                                              audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1207 | { | 
 | 1208 |     ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session); | 
 | 1209 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 1210 |     if (index < 0) { | 
 | 1211 |         ALOGW("startOutput() unknown output %d", output); | 
 | 1212 |         return BAD_VALUE; | 
 | 1213 |     } | 
 | 1214 |  | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 1215 |     // cannot start playback of STREAM_TTS if any other output is being used | 
 | 1216 |     uint32_t beaconMuteLatency = 0; | 
 | 1217 |     if (stream == AUDIO_STREAM_TTS) { | 
 | 1218 |         ALOGV("\t found BEACON stream"); | 
 | 1219 |         if (isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) { | 
 | 1220 |             return INVALID_OPERATION; | 
 | 1221 |         } else { | 
 | 1222 |             beaconMuteLatency = handleEventForBeacon(STARTING_BEACON); | 
 | 1223 |         } | 
 | 1224 |     } else { | 
 | 1225 |         // some playback other than beacon starts | 
 | 1226 |         beaconMuteLatency = handleEventForBeacon(STARTING_OUTPUT); | 
 | 1227 |     } | 
 | 1228 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1229 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1230 |  | 
 | 1231 |     // increment usage count for this stream on the requested output: | 
 | 1232 |     // NOTE that the usage count is the same for duplicated output and hardware output which is | 
 | 1233 |     // necessary for a correct control of hardware output routing by startOutput() and stopOutput() | 
 | 1234 |     outputDesc->changeRefCount(stream, 1); | 
 | 1235 |  | 
 | 1236 |     if (outputDesc->mRefCount[stream] == 1) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1237 |         // starting an output being rerouted? | 
 | 1238 |         audio_devices_t newDevice; | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1239 |         if (outputDesc->mPolicyMix != NULL) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1240 |             newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX; | 
 | 1241 |         } else { | 
 | 1242 |             newDevice = getNewOutputDevice(output, false /*fromCache*/); | 
 | 1243 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1244 |         routing_strategy strategy = getStrategy(stream); | 
 | 1245 |         bool shouldWait = (strategy == STRATEGY_SONIFICATION) || | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 1246 |                             (strategy == STRATEGY_SONIFICATION_RESPECTFUL) || | 
 | 1247 |                             (beaconMuteLatency > 0); | 
 | 1248 |         uint32_t waitMs = beaconMuteLatency; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1249 |         bool force = false; | 
 | 1250 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1251 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1252 |             if (desc != outputDesc) { | 
 | 1253 |                 // force a device change if any other output is managed by the same hw | 
 | 1254 |                 // module and has a current device selection that differs from selected device. | 
 | 1255 |                 // In this case, the audio HAL must receive the new device selection so that it can | 
 | 1256 |                 // change the device currently selected by the other active output. | 
 | 1257 |                 if (outputDesc->sharesHwModuleWith(desc) && | 
 | 1258 |                     desc->device() != newDevice) { | 
 | 1259 |                     force = true; | 
 | 1260 |                 } | 
 | 1261 |                 // wait for audio on other active outputs to be presented when starting | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 1262 |                 // a notification so that audio focus effect can propagate, or that a mute/unmute | 
 | 1263 |                 // event occurred for beacon | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1264 |                 uint32_t latency = desc->latency(); | 
 | 1265 |                 if (shouldWait && desc->isActive(latency * 2) && (waitMs < latency)) { | 
 | 1266 |                     waitMs = latency; | 
 | 1267 |                 } | 
 | 1268 |             } | 
 | 1269 |         } | 
 | 1270 |         uint32_t muteWaitMs = setOutputDevice(output, newDevice, force); | 
 | 1271 |  | 
 | 1272 |         // handle special case for sonification while in call | 
 | 1273 |         if (isInCall()) { | 
 | 1274 |             handleIncallSonification(stream, true, false); | 
 | 1275 |         } | 
 | 1276 |  | 
 | 1277 |         // apply volume rules for current stream and device if necessary | 
 | 1278 |         checkAndSetVolume(stream, | 
 | 1279 |                           mStreams[stream].getVolumeIndex(newDevice), | 
 | 1280 |                           output, | 
 | 1281 |                           newDevice); | 
 | 1282 |  | 
 | 1283 |         // update the outputs if starting an output with a stream that can affect notification | 
 | 1284 |         // routing | 
 | 1285 |         handleNotificationRoutingForStream(stream); | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1286 |  | 
 | 1287 |         // Automatically enable the remote submix input when output is started on a re routing mix | 
 | 1288 |         // of type MIX_TYPE_RECORDERS | 
 | 1289 |         if (audio_is_remote_submix_device(newDevice) && outputDesc->mPolicyMix != NULL && | 
 | 1290 |                 outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 1291 |                 setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1292 |                         AUDIO_POLICY_DEVICE_STATE_AVAILABLE, | 
 | 1293 |                         outputDesc->mPolicyMix->mRegistrationId); | 
 | 1294 |         } | 
 | 1295 |  | 
| Eric Laurent | 2cbe89a | 2014-12-19 11:49:08 -0800 | [diff] [blame] | 1296 |         // force reevaluating accessibility routing when ringtone or alarm starts | 
 | 1297 |         if (strategy == STRATEGY_SONIFICATION) { | 
 | 1298 |             mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY); | 
 | 1299 |         } | 
 | 1300 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1301 |         if (waitMs > muteWaitMs) { | 
 | 1302 |             usleep((waitMs - muteWaitMs) * 2 * 1000); | 
 | 1303 |         } | 
 | 1304 |     } | 
 | 1305 |     return NO_ERROR; | 
 | 1306 | } | 
 | 1307 |  | 
 | 1308 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1309 | status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1310 |                                             audio_stream_type_t stream, | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 1311 |                                             audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1312 | { | 
 | 1313 |     ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session); | 
 | 1314 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 1315 |     if (index < 0) { | 
 | 1316 |         ALOGW("stopOutput() unknown output %d", output); | 
 | 1317 |         return BAD_VALUE; | 
 | 1318 |     } | 
 | 1319 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1320 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1321 |  | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 1322 |     // always handle stream stop, check which stream type is stopping | 
 | 1323 |     handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT); | 
 | 1324 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1325 |     // handle special case for sonification while in call | 
 | 1326 |     if (isInCall()) { | 
 | 1327 |         handleIncallSonification(stream, false, false); | 
 | 1328 |     } | 
 | 1329 |  | 
 | 1330 |     if (outputDesc->mRefCount[stream] > 0) { | 
 | 1331 |         // decrement usage count of this stream on the output | 
 | 1332 |         outputDesc->changeRefCount(stream, -1); | 
 | 1333 |         // store time at which the stream was stopped - see isStreamActive() | 
 | 1334 |         if (outputDesc->mRefCount[stream] == 0) { | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1335 |             // Automatically disable the remote submix input when output is stopped on a | 
 | 1336 |             // re routing mix of type MIX_TYPE_RECORDERS | 
 | 1337 |             if (audio_is_remote_submix_device(outputDesc->mDevice) && | 
 | 1338 |                     outputDesc->mPolicyMix != NULL && | 
 | 1339 |                     outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 1340 |                 setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1341 |                         AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, | 
 | 1342 |                         outputDesc->mPolicyMix->mRegistrationId); | 
 | 1343 |             } | 
 | 1344 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1345 |             outputDesc->mStopTime[stream] = systemTime(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1346 |             audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1347 |             // delay the device switch by twice the latency because stopOutput() is executed when | 
 | 1348 |             // the track stop() command is received and at that time the audio track buffer can | 
 | 1349 |             // still contain data that needs to be drained. The latency only covers the audio HAL | 
 | 1350 |             // and kernel buffers. Also the latency does not always include additional delay in the | 
 | 1351 |             // audio path (audio DSP, CODEC ...) | 
 | 1352 |             setOutputDevice(output, newDevice, false, outputDesc->mLatency*2); | 
 | 1353 |  | 
 | 1354 |             // force restoring the device selection on other active outputs if it differs from the | 
 | 1355 |             // one being selected for this output | 
 | 1356 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1357 |                 audio_io_handle_t curOutput = mOutputs.keyAt(i); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1358 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1359 |                 if (curOutput != output && | 
 | 1360 |                         desc->isActive() && | 
 | 1361 |                         outputDesc->sharesHwModuleWith(desc) && | 
 | 1362 |                         (newDevice != desc->device())) { | 
 | 1363 |                     setOutputDevice(curOutput, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1364 |                                     getNewOutputDevice(curOutput, false /*fromCache*/), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1365 |                                     true, | 
 | 1366 |                                     outputDesc->mLatency*2); | 
 | 1367 |                 } | 
 | 1368 |             } | 
 | 1369 |             // update the outputs if stopping one with a stream that can affect notification routing | 
 | 1370 |             handleNotificationRoutingForStream(stream); | 
 | 1371 |         } | 
 | 1372 |         return NO_ERROR; | 
 | 1373 |     } else { | 
 | 1374 |         ALOGW("stopOutput() refcount is already 0 for output %d", output); | 
 | 1375 |         return INVALID_OPERATION; | 
 | 1376 |     } | 
 | 1377 | } | 
 | 1378 |  | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 1379 | void AudioPolicyManager::releaseOutput(audio_io_handle_t output, | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1380 |                                        audio_stream_type_t stream __unused, | 
 | 1381 |                                        audio_session_t session __unused) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1382 | { | 
 | 1383 |     ALOGV("releaseOutput() %d", output); | 
 | 1384 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 1385 |     if (index < 0) { | 
 | 1386 |         ALOGW("releaseOutput() releasing unknown output %d", output); | 
 | 1387 |         return; | 
 | 1388 |     } | 
 | 1389 |  | 
 | 1390 | #ifdef AUDIO_POLICY_TEST | 
 | 1391 |     int testIndex = testOutputIndex(output); | 
 | 1392 |     if (testIndex != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1393 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1394 |         if (outputDesc->isActive()) { | 
 | 1395 |             mpClientInterface->closeOutput(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1396 |             mOutputs.removeItem(output); | 
 | 1397 |             mTestOutputs[testIndex] = 0; | 
 | 1398 |         } | 
 | 1399 |         return; | 
 | 1400 |     } | 
 | 1401 | #endif //AUDIO_POLICY_TEST | 
 | 1402 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1403 |     sp<AudioOutputDescriptor> desc = mOutputs.valueAt(index); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1404 |     if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1405 |         if (desc->mDirectOpenCount <= 0) { | 
 | 1406 |             ALOGW("releaseOutput() invalid open count %d for output %d", | 
 | 1407 |                                                               desc->mDirectOpenCount, output); | 
 | 1408 |             return; | 
 | 1409 |         } | 
 | 1410 |         if (--desc->mDirectOpenCount == 0) { | 
 | 1411 |             closeOutput(output); | 
 | 1412 |             // If effects where present on the output, audioflinger moved them to the primary | 
 | 1413 |             // output by default: move them back to the appropriate output. | 
 | 1414 |             audio_io_handle_t dstOutput = getOutputForEffect(); | 
 | 1415 |             if (dstOutput != mPrimaryOutput) { | 
 | 1416 |                 mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput); | 
 | 1417 |             } | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1418 |             mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1419 |         } | 
 | 1420 |     } | 
 | 1421 | } | 
 | 1422 |  | 
 | 1423 |  | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1424 | status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, | 
 | 1425 |                                              audio_io_handle_t *input, | 
 | 1426 |                                              audio_session_t session, | 
 | 1427 |                                              uint32_t samplingRate, | 
 | 1428 |                                              audio_format_t format, | 
 | 1429 |                                              audio_channel_mask_t channelMask, | 
| Jean-Michel Trivi | 97bb33f | 2014-12-12 16:23:43 -0800 | [diff] [blame] | 1430 |                                              audio_input_flags_t flags, | 
 | 1431 |                                              input_type_t *inputType) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1432 | { | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1433 |     ALOGV("getInputForAttr() source %d, samplingRate %d, format %d, channelMask %x," | 
 | 1434 |             "session %d, flags %#x", | 
 | 1435 |           attr->source, samplingRate, format, channelMask, session, flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1436 |  | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1437 |     *input = AUDIO_IO_HANDLE_NONE; | 
| Jean-Michel Trivi | 97bb33f | 2014-12-12 16:23:43 -0800 | [diff] [blame] | 1438 |     *inputType = API_INPUT_INVALID; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1439 |     audio_devices_t device; | 
 | 1440 |     // handle legacy remote submix case where the address was not always specified | 
 | 1441 |     String8 address = String8(""); | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 1442 |     bool isSoundTrigger = false; | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1443 |     audio_source_t inputSource = attr->source; | 
 | 1444 |     audio_source_t halInputSource; | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1445 |     AudioMix *policyMix = NULL; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1446 |  | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1447 |     if (inputSource == AUDIO_SOURCE_DEFAULT) { | 
 | 1448 |         inputSource = AUDIO_SOURCE_MIC; | 
 | 1449 |     } | 
 | 1450 |     halInputSource = inputSource; | 
 | 1451 |  | 
 | 1452 |     if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX && | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1453 |             strncmp(attr->tags, "addr=", strlen("addr=")) == 0) { | 
 | 1454 |         device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; | 
 | 1455 |         address = String8(attr->tags + strlen("addr=")); | 
 | 1456 |         ssize_t index = mPolicyMixes.indexOfKey(address); | 
 | 1457 |         if (index < 0) { | 
 | 1458 |             ALOGW("getInputForAttr() no policy for address %s", address.string()); | 
 | 1459 |             return BAD_VALUE; | 
 | 1460 |         } | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1461 |         if (mPolicyMixes[index]->mMix.mMixType != MIX_TYPE_PLAYERS) { | 
 | 1462 |             ALOGW("getInputForAttr() bad policy mix type for address %s", address.string()); | 
 | 1463 |             return BAD_VALUE; | 
 | 1464 |         } | 
 | 1465 |         policyMix = &mPolicyMixes[index]->mMix; | 
| Jean-Michel Trivi | 97bb33f | 2014-12-12 16:23:43 -0800 | [diff] [blame] | 1466 |         *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1467 |     } else { | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1468 |         device = getDeviceAndMixForInputSource(inputSource, &policyMix); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1469 |         if (device == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1470 |             ALOGW("getInputForAttr() could not find device for source %d", inputSource); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1471 |             return BAD_VALUE; | 
 | 1472 |         } | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1473 |         if (policyMix != NULL) { | 
 | 1474 |             address = policyMix->mRegistrationId; | 
| Jean-Michel Trivi | 97bb33f | 2014-12-12 16:23:43 -0800 | [diff] [blame] | 1475 |             if (policyMix->mMixType == MIX_TYPE_RECORDERS) { | 
 | 1476 |                 // there is an external policy, but this input is attached to a mix of recorders, | 
 | 1477 |                 // meaning it receives audio injected into the framework, so the recorder doesn't | 
 | 1478 |                 // know about it and is therefore considered "legacy" | 
 | 1479 |                 *inputType = API_INPUT_LEGACY; | 
 | 1480 |             } else { | 
 | 1481 |                 // recording a mix of players defined by an external policy, we're rerouting for | 
 | 1482 |                 // an external policy | 
 | 1483 |                 *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE; | 
 | 1484 |             } | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1485 |         } else if (audio_is_remote_submix_device(device)) { | 
 | 1486 |             address = String8("0"); | 
| Jean-Michel Trivi | 97bb33f | 2014-12-12 16:23:43 -0800 | [diff] [blame] | 1487 |             *inputType = API_INPUT_MIX_CAPTURE; | 
 | 1488 |         } else { | 
 | 1489 |             *inputType = API_INPUT_LEGACY; | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1490 |         } | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1491 |         // adapt channel selection to input source | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1492 |         switch (inputSource) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1493 |         case AUDIO_SOURCE_VOICE_UPLINK: | 
 | 1494 |             channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK; | 
 | 1495 |             break; | 
 | 1496 |         case AUDIO_SOURCE_VOICE_DOWNLINK: | 
 | 1497 |             channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK; | 
 | 1498 |             break; | 
 | 1499 |         case AUDIO_SOURCE_VOICE_CALL: | 
 | 1500 |             channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK; | 
 | 1501 |             break; | 
 | 1502 |         default: | 
 | 1503 |             break; | 
 | 1504 |         } | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1505 |         if (inputSource == AUDIO_SOURCE_HOTWORD) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1506 |             ssize_t index = mSoundTriggerSessions.indexOfKey(session); | 
 | 1507 |             if (index >= 0) { | 
 | 1508 |                 *input = mSoundTriggerSessions.valueFor(session); | 
 | 1509 |                 isSoundTrigger = true; | 
 | 1510 |                 flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD); | 
 | 1511 |                 ALOGV("SoundTrigger capture on session %d input %d", session, *input); | 
 | 1512 |             } else { | 
 | 1513 |                 halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION; | 
 | 1514 |             } | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 1515 |         } | 
 | 1516 |     } | 
 | 1517 |  | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1518 |     sp<IOProfile> profile = getInputProfile(device, address, | 
 | 1519 |                                             samplingRate, format, channelMask, | 
 | 1520 |                                             flags); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1521 |     if (profile == 0) { | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 1522 |         //retry without flags | 
 | 1523 |         audio_input_flags_t log_flags = flags; | 
 | 1524 |         flags = AUDIO_INPUT_FLAG_NONE; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 1525 |         profile = getInputProfile(device, address, | 
 | 1526 |                                   samplingRate, format, channelMask, | 
 | 1527 |                                   flags); | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 1528 |         if (profile == 0) { | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1529 |             ALOGW("getInputForAttr() could not find profile for device 0x%X, samplingRate %u," | 
 | 1530 |                     "format %#x, channelMask 0x%X, flags %#x", | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 1531 |                     device, samplingRate, format, channelMask, log_flags); | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1532 |             return BAD_VALUE; | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 1533 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1534 |     } | 
 | 1535 |  | 
 | 1536 |     if (profile->mModule->mHandle == 0) { | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1537 |         ALOGE("getInputForAttr(): HW module %s not opened", profile->mModule->mName); | 
 | 1538 |         return NO_INIT; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1539 |     } | 
 | 1540 |  | 
 | 1541 |     audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 1542 |     config.sample_rate = samplingRate; | 
 | 1543 |     config.channel_mask = channelMask; | 
 | 1544 |     config.format = format; | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 1545 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1546 |     status_t status = mpClientInterface->openInput(profile->mModule->mHandle, | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1547 |                                                    input, | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1548 |                                                    &config, | 
 | 1549 |                                                    &device, | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 1550 |                                                    address, | 
| Eric Laurent | 1c9c2cc | 2014-08-28 19:37:25 -0700 | [diff] [blame] | 1551 |                                                    halInputSource, | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1552 |                                                    flags); | 
 | 1553 |  | 
 | 1554 |     // only accept input with the exact requested set of parameters | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1555 |     if (status != NO_ERROR || *input == AUDIO_IO_HANDLE_NONE || | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1556 |         (samplingRate != config.sample_rate) || | 
 | 1557 |         (format != config.format) || | 
 | 1558 |         (channelMask != config.channel_mask)) { | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1559 |         ALOGW("getInputForAttr() failed opening input: samplingRate %d, format %d, channelMask %x", | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1560 |                 samplingRate, format, channelMask); | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1561 |         if (*input != AUDIO_IO_HANDLE_NONE) { | 
 | 1562 |             mpClientInterface->closeInput(*input); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1563 |         } | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1564 |         return BAD_VALUE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1565 |     } | 
 | 1566 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1567 |     sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile); | 
| Eric Laurent | c447ded | 2015-01-06 08:47:05 -0800 | [diff] [blame^] | 1568 |     inputDesc->mInputSource = inputSource; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1569 |     inputDesc->mRefCount = 0; | 
 | 1570 |     inputDesc->mOpenRefCount = 1; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1571 |     inputDesc->mSamplingRate = samplingRate; | 
 | 1572 |     inputDesc->mFormat = format; | 
 | 1573 |     inputDesc->mChannelMask = channelMask; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1574 |     inputDesc->mDevice = device; | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1575 |     inputDesc->mSessions.add(session); | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 1576 |     inputDesc->mIsSoundTrigger = isSoundTrigger; | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1577 |     inputDesc->mPolicyMix = policyMix; | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1578 |  | 
| Jean-Michel Trivi | 97bb33f | 2014-12-12 16:23:43 -0800 | [diff] [blame] | 1579 |     ALOGV("getInputForAttr() returns input type = %d", inputType); | 
 | 1580 |  | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1581 |     addInput(*input, inputDesc); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1582 |     mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | caf7f48 | 2014-11-25 17:50:47 -0800 | [diff] [blame] | 1583 |     return NO_ERROR; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1584 | } | 
 | 1585 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1586 | status_t AudioPolicyManager::startInput(audio_io_handle_t input, | 
 | 1587 |                                         audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1588 | { | 
 | 1589 |     ALOGV("startInput() input %d", input); | 
 | 1590 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1591 |     if (index < 0) { | 
 | 1592 |         ALOGW("startInput() unknown input %d", input); | 
 | 1593 |         return BAD_VALUE; | 
 | 1594 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1595 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1596 |  | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1597 |     index = inputDesc->mSessions.indexOf(session); | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1598 |     if (index < 0) { | 
 | 1599 |         ALOGW("startInput() unknown session %d on input %d", session, input); | 
 | 1600 |         return BAD_VALUE; | 
 | 1601 |     } | 
 | 1602 |  | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1603 |     // virtual input devices are compatible with other input devices | 
 | 1604 |     if (!isVirtualInputDevice(inputDesc->mDevice)) { | 
 | 1605 |  | 
 | 1606 |         // for a non-virtual input device, check if there is another (non-virtual) active input | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1607 |         audio_io_handle_t activeInput = getActiveInput(); | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1608 |         if (activeInput != 0 && activeInput != input) { | 
 | 1609 |  | 
 | 1610 |             // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed, | 
 | 1611 |             // otherwise the active input continues and the new input cannot be started. | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1612 |             sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1613 |             if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) { | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1614 |                 ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput); | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1615 |                 stopInput(activeInput, activeDesc->mSessions.itemAt(0)); | 
 | 1616 |                 releaseInput(activeInput, activeDesc->mSessions.itemAt(0)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1617 |             } else { | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1618 |                 ALOGE("startInput(%d) failed: other input %d already started", input, activeInput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1619 |                 return INVALID_OPERATION; | 
 | 1620 |             } | 
 | 1621 |         } | 
 | 1622 |     } | 
 | 1623 |  | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1624 |     if (inputDesc->mRefCount == 0) { | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 1625 |         if (activeInputsCount() == 0) { | 
 | 1626 |             SoundTrigger::setCaptureState(true); | 
 | 1627 |         } | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1628 |         setInputDevice(input, getNewInputDevice(input), true /* force */); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1629 |  | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1630 |         // automatically enable the remote submix output when input is started if not | 
 | 1631 |         // used by a policy mix of type MIX_TYPE_RECORDERS | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1632 |         // For remote submix (a virtual device), we open only one input per capture request. | 
 | 1633 |         if (audio_is_remote_submix_device(inputDesc->mDevice)) { | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1634 |             String8 address = String8(""); | 
 | 1635 |             if (inputDesc->mPolicyMix == NULL) { | 
 | 1636 |                 address = String8("0"); | 
 | 1637 |             } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) { | 
 | 1638 |                 address = inputDesc->mPolicyMix->mRegistrationId; | 
 | 1639 |             } | 
 | 1640 |             if (address != "") { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 1641 |                 setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1642 |                         AUDIO_POLICY_DEVICE_STATE_AVAILABLE, | 
 | 1643 |                         address); | 
 | 1644 |             } | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1645 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1646 |     } | 
 | 1647 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1648 |     ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource); | 
 | 1649 |  | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1650 |     inputDesc->mRefCount++; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1651 |     return NO_ERROR; | 
 | 1652 | } | 
 | 1653 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1654 | status_t AudioPolicyManager::stopInput(audio_io_handle_t input, | 
 | 1655 |                                        audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1656 | { | 
 | 1657 |     ALOGV("stopInput() input %d", input); | 
 | 1658 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1659 |     if (index < 0) { | 
 | 1660 |         ALOGW("stopInput() unknown input %d", input); | 
 | 1661 |         return BAD_VALUE; | 
 | 1662 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1663 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1664 |  | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1665 |     index = inputDesc->mSessions.indexOf(session); | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1666 |     if (index < 0) { | 
 | 1667 |         ALOGW("stopInput() unknown session %d on input %d", session, input); | 
 | 1668 |         return BAD_VALUE; | 
 | 1669 |     } | 
 | 1670 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1671 |     if (inputDesc->mRefCount == 0) { | 
 | 1672 |         ALOGW("stopInput() input %d already stopped", input); | 
 | 1673 |         return INVALID_OPERATION; | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1674 |     } | 
 | 1675 |  | 
 | 1676 |     inputDesc->mRefCount--; | 
 | 1677 |     if (inputDesc->mRefCount == 0) { | 
 | 1678 |  | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1679 |         // automatically disable the remote submix output when input is stopped if not | 
 | 1680 |         // used by a policy mix of type MIX_TYPE_RECORDERS | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1681 |         if (audio_is_remote_submix_device(inputDesc->mDevice)) { | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1682 |             String8 address = String8(""); | 
 | 1683 |             if (inputDesc->mPolicyMix == NULL) { | 
 | 1684 |                 address = String8("0"); | 
 | 1685 |             } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) { | 
 | 1686 |                 address = inputDesc->mPolicyMix->mRegistrationId; | 
 | 1687 |             } | 
 | 1688 |             if (address != "") { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 1689 |                 setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1690 |                                          AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, | 
 | 1691 |                                          address); | 
 | 1692 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1693 |         } | 
 | 1694 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1695 |         resetInputDevice(input); | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 1696 |  | 
 | 1697 |         if (activeInputsCount() == 0) { | 
 | 1698 |             SoundTrigger::setCaptureState(false); | 
 | 1699 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1700 |     } | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1701 |     return NO_ERROR; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1702 | } | 
 | 1703 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1704 | void AudioPolicyManager::releaseInput(audio_io_handle_t input, | 
 | 1705 |                                       audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1706 | { | 
 | 1707 |     ALOGV("releaseInput() %d", input); | 
 | 1708 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1709 |     if (index < 0) { | 
 | 1710 |         ALOGW("releaseInput() releasing unknown input %d", input); | 
 | 1711 |         return; | 
 | 1712 |     } | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1713 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
 | 1714 |     ALOG_ASSERT(inputDesc != 0); | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1715 |  | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1716 |     index = inputDesc->mSessions.indexOf(session); | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1717 |     if (index < 0) { | 
 | 1718 |         ALOGW("releaseInput() unknown session %d on input %d", session, input); | 
 | 1719 |         return; | 
 | 1720 |     } | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 1721 |     inputDesc->mSessions.remove(session); | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1722 |     if (inputDesc->mOpenRefCount == 0) { | 
 | 1723 |         ALOGW("releaseInput() invalid open ref count %d", inputDesc->mOpenRefCount); | 
 | 1724 |         return; | 
 | 1725 |     } | 
 | 1726 |     inputDesc->mOpenRefCount--; | 
 | 1727 |     if (inputDesc->mOpenRefCount > 0) { | 
 | 1728 |         ALOGV("releaseInput() exit > 0"); | 
 | 1729 |         return; | 
 | 1730 |     } | 
 | 1731 |  | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 1732 |     closeInput(input); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1733 |     mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1734 |     ALOGV("releaseInput() exit"); | 
 | 1735 | } | 
 | 1736 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1737 | void AudioPolicyManager::closeAllInputs() { | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 1738 |     bool patchRemoved = false; | 
 | 1739 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1740 |     for(size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 1741 |         sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index); | 
 | 1742 |         ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 1743 |         if (patch_index >= 0) { | 
 | 1744 |             sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index); | 
 | 1745 |             status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
 | 1746 |             mAudioPatches.removeItemsAt(patch_index); | 
 | 1747 |             patchRemoved = true; | 
 | 1748 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1749 |         mpClientInterface->closeInput(mInputs.keyAt(input_index)); | 
 | 1750 |     } | 
 | 1751 |     mInputs.clear(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1752 |     nextAudioPortGeneration(); | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 1753 |  | 
 | 1754 |     if (patchRemoved) { | 
 | 1755 |         mpClientInterface->onAudioPatchListUpdate(); | 
 | 1756 |     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1757 | } | 
 | 1758 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1759 | void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1760 |                                             int indexMin, | 
 | 1761 |                                             int indexMax) | 
 | 1762 | { | 
 | 1763 |     ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax); | 
 | 1764 |     if (indexMin < 0 || indexMin >= indexMax) { | 
 | 1765 |         ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax); | 
 | 1766 |         return; | 
 | 1767 |     } | 
 | 1768 |     mStreams[stream].mIndexMin = indexMin; | 
 | 1769 |     mStreams[stream].mIndexMax = indexMax; | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 1770 |     //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now | 
 | 1771 |     if (stream == AUDIO_STREAM_MUSIC) { | 
 | 1772 |         mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMin = indexMin; | 
 | 1773 |         mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMax = indexMax; | 
 | 1774 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1775 | } | 
 | 1776 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1777 | status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1778 |                                                       int index, | 
 | 1779 |                                                       audio_devices_t device) | 
 | 1780 | { | 
 | 1781 |  | 
 | 1782 |     if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) { | 
 | 1783 |         return BAD_VALUE; | 
 | 1784 |     } | 
 | 1785 |     if (!audio_is_output_device(device)) { | 
 | 1786 |         return BAD_VALUE; | 
 | 1787 |     } | 
 | 1788 |  | 
 | 1789 |     // Force max volume if stream cannot be muted | 
 | 1790 |     if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax; | 
 | 1791 |  | 
 | 1792 |     ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d", | 
 | 1793 |           stream, device, index); | 
 | 1794 |  | 
 | 1795 |     // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and | 
 | 1796 |     // clear all device specific values | 
 | 1797 |     if (device == AUDIO_DEVICE_OUT_DEFAULT) { | 
 | 1798 |         mStreams[stream].mIndexCur.clear(); | 
 | 1799 |     } | 
 | 1800 |     mStreams[stream].mIndexCur.add(device, index); | 
 | 1801 |  | 
| Eric Laurent | 31551f8 | 2014-10-10 18:21:56 -0700 | [diff] [blame] | 1802 |     // update volume on all outputs whose current device is also selected by the same | 
 | 1803 |     // strategy as the device specified by the caller | 
 | 1804 |     audio_devices_t strategyDevice = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/); | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 1805 |  | 
 | 1806 |  | 
 | 1807 |     //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now | 
 | 1808 |     audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE; | 
 | 1809 |     if (stream == AUDIO_STREAM_MUSIC) { | 
 | 1810 |         mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index); | 
 | 1811 |         accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/); | 
 | 1812 |     } | 
 | 1813 |     if ((device != AUDIO_DEVICE_OUT_DEFAULT) && | 
 | 1814 |             (device & (strategyDevice | accessibilityDevice)) == 0) { | 
| Eric Laurent | 31551f8 | 2014-10-10 18:21:56 -0700 | [diff] [blame] | 1815 |         return NO_ERROR; | 
 | 1816 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1817 |     status_t status = NO_ERROR; | 
 | 1818 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1819 |         audio_devices_t curDevice = | 
 | 1820 |                 getDeviceForVolume(mOutputs.valueAt(i)->device()); | 
| Eric Laurent | 31551f8 | 2014-10-10 18:21:56 -0700 | [diff] [blame] | 1821 |         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1822 |             status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice); | 
 | 1823 |             if (volStatus != NO_ERROR) { | 
 | 1824 |                 status = volStatus; | 
 | 1825 |             } | 
 | 1826 |         } | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 1827 |         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) { | 
 | 1828 |             status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY, | 
 | 1829 |                                                    index, mOutputs.keyAt(i), curDevice); | 
 | 1830 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1831 |     } | 
 | 1832 |     return status; | 
 | 1833 | } | 
 | 1834 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1835 | status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1836 |                                                       int *index, | 
 | 1837 |                                                       audio_devices_t device) | 
 | 1838 | { | 
 | 1839 |     if (index == NULL) { | 
 | 1840 |         return BAD_VALUE; | 
 | 1841 |     } | 
 | 1842 |     if (!audio_is_output_device(device)) { | 
 | 1843 |         return BAD_VALUE; | 
 | 1844 |     } | 
 | 1845 |     // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to | 
 | 1846 |     // the strategy the stream belongs to. | 
 | 1847 |     if (device == AUDIO_DEVICE_OUT_DEFAULT) { | 
 | 1848 |         device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/); | 
 | 1849 |     } | 
 | 1850 |     device = getDeviceForVolume(device); | 
 | 1851 |  | 
 | 1852 |     *index =  mStreams[stream].getVolumeIndex(device); | 
 | 1853 |     ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index); | 
 | 1854 |     return NO_ERROR; | 
 | 1855 | } | 
 | 1856 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1857 | audio_io_handle_t AudioPolicyManager::selectOutputForEffects( | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1858 |                                             const SortedVector<audio_io_handle_t>& outputs) | 
 | 1859 | { | 
 | 1860 |     // select one output among several suitable for global effects. | 
 | 1861 |     // The priority is as follows: | 
 | 1862 |     // 1: An offloaded output. If the effect ends up not being offloadable, | 
 | 1863 |     //    AudioFlinger will invalidate the track and the offloaded output | 
 | 1864 |     //    will be closed causing the effect to be moved to a PCM output. | 
 | 1865 |     // 2: A deep buffer output | 
 | 1866 |     // 3: the first output in the list | 
 | 1867 |  | 
 | 1868 |     if (outputs.size() == 0) { | 
 | 1869 |         return 0; | 
 | 1870 |     } | 
 | 1871 |  | 
 | 1872 |     audio_io_handle_t outputOffloaded = 0; | 
 | 1873 |     audio_io_handle_t outputDeepBuffer = 0; | 
 | 1874 |  | 
 | 1875 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1876 |         sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1877 |         ALOGV("selectOutputForEffects outputs[%zu] flags %x", i, desc->mFlags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1878 |         if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
 | 1879 |             outputOffloaded = outputs[i]; | 
 | 1880 |         } | 
 | 1881 |         if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) { | 
 | 1882 |             outputDeepBuffer = outputs[i]; | 
 | 1883 |         } | 
 | 1884 |     } | 
 | 1885 |  | 
 | 1886 |     ALOGV("selectOutputForEffects outputOffloaded %d outputDeepBuffer %d", | 
 | 1887 |           outputOffloaded, outputDeepBuffer); | 
 | 1888 |     if (outputOffloaded != 0) { | 
 | 1889 |         return outputOffloaded; | 
 | 1890 |     } | 
 | 1891 |     if (outputDeepBuffer != 0) { | 
 | 1892 |         return outputDeepBuffer; | 
 | 1893 |     } | 
 | 1894 |  | 
 | 1895 |     return outputs[0]; | 
 | 1896 | } | 
 | 1897 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1898 | audio_io_handle_t AudioPolicyManager::getOutputForEffect(const effect_descriptor_t *desc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1899 | { | 
 | 1900 |     // apply simple rule where global effects are attached to the same output as MUSIC streams | 
 | 1901 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1902 |     routing_strategy strategy = getStrategy(AUDIO_STREAM_MUSIC); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1903 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 1904 |     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(device, mOutputs); | 
 | 1905 |  | 
 | 1906 |     audio_io_handle_t output = selectOutputForEffects(dstOutputs); | 
 | 1907 |     ALOGV("getOutputForEffect() got output %d for fx %s flags %x", | 
 | 1908 |           output, (desc == NULL) ? "unspecified" : desc->name,  (desc == NULL) ? 0 : desc->flags); | 
 | 1909 |  | 
 | 1910 |     return output; | 
 | 1911 | } | 
 | 1912 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1913 | status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1914 |                                 audio_io_handle_t io, | 
 | 1915 |                                 uint32_t strategy, | 
 | 1916 |                                 int session, | 
 | 1917 |                                 int id) | 
 | 1918 | { | 
 | 1919 |     ssize_t index = mOutputs.indexOfKey(io); | 
 | 1920 |     if (index < 0) { | 
 | 1921 |         index = mInputs.indexOfKey(io); | 
 | 1922 |         if (index < 0) { | 
 | 1923 |             ALOGW("registerEffect() unknown io %d", io); | 
 | 1924 |             return INVALID_OPERATION; | 
 | 1925 |         } | 
 | 1926 |     } | 
 | 1927 |  | 
 | 1928 |     if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) { | 
 | 1929 |         ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB", | 
 | 1930 |                 desc->name, desc->memoryUsage); | 
 | 1931 |         return INVALID_OPERATION; | 
 | 1932 |     } | 
 | 1933 |     mTotalEffectsMemory += desc->memoryUsage; | 
 | 1934 |     ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d", | 
 | 1935 |             desc->name, io, strategy, session, id); | 
 | 1936 |     ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory); | 
 | 1937 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1938 |     sp<EffectDescriptor> effectDesc = new EffectDescriptor(); | 
 | 1939 |     memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t)); | 
 | 1940 |     effectDesc->mIo = io; | 
 | 1941 |     effectDesc->mStrategy = (routing_strategy)strategy; | 
 | 1942 |     effectDesc->mSession = session; | 
 | 1943 |     effectDesc->mEnabled = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1944 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1945 |     mEffects.add(id, effectDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1946 |  | 
 | 1947 |     return NO_ERROR; | 
 | 1948 | } | 
 | 1949 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1950 | status_t AudioPolicyManager::unregisterEffect(int id) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1951 | { | 
 | 1952 |     ssize_t index = mEffects.indexOfKey(id); | 
 | 1953 |     if (index < 0) { | 
 | 1954 |         ALOGW("unregisterEffect() unknown effect ID %d", id); | 
 | 1955 |         return INVALID_OPERATION; | 
 | 1956 |     } | 
 | 1957 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1958 |     sp<EffectDescriptor> effectDesc = mEffects.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1959 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1960 |     setEffectEnabled(effectDesc, false); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1961 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1962 |     if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1963 |         ALOGW("unregisterEffect() memory %d too big for total %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1964 |                 effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); | 
 | 1965 |         effectDesc->mDesc.memoryUsage = mTotalEffectsMemory; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1966 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1967 |     mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1968 |     ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1969 |             effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1970 |  | 
 | 1971 |     mEffects.removeItem(id); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1972 |  | 
 | 1973 |     return NO_ERROR; | 
 | 1974 | } | 
 | 1975 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1976 | status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1977 | { | 
 | 1978 |     ssize_t index = mEffects.indexOfKey(id); | 
 | 1979 |     if (index < 0) { | 
 | 1980 |         ALOGW("unregisterEffect() unknown effect ID %d", id); | 
 | 1981 |         return INVALID_OPERATION; | 
 | 1982 |     } | 
 | 1983 |  | 
 | 1984 |     return setEffectEnabled(mEffects.valueAt(index), enabled); | 
 | 1985 | } | 
 | 1986 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1987 | status_t AudioPolicyManager::setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1988 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1989 |     if (enabled == effectDesc->mEnabled) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1990 |         ALOGV("setEffectEnabled(%s) effect already %s", | 
 | 1991 |              enabled?"true":"false", enabled?"enabled":"disabled"); | 
 | 1992 |         return INVALID_OPERATION; | 
 | 1993 |     } | 
 | 1994 |  | 
 | 1995 |     if (enabled) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1996 |         if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1997 |             ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1998 |                  effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1999 |             return INVALID_OPERATION; | 
 | 2000 |         } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2001 |         mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2002 |         ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad); | 
 | 2003 |     } else { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2004 |         if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2005 |             ALOGW("setEffectEnabled(false) CPU load %d too high for total %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2006 |                     effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad); | 
 | 2007 |             effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2008 |         } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2009 |         mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2010 |         ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad); | 
 | 2011 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2012 |     effectDesc->mEnabled = enabled; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2013 |     return NO_ERROR; | 
 | 2014 | } | 
 | 2015 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2016 | bool AudioPolicyManager::isNonOffloadableEffectEnabled() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2017 | { | 
 | 2018 |     for (size_t i = 0; i < mEffects.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2019 |         sp<EffectDescriptor> effectDesc = mEffects.valueAt(i); | 
 | 2020 |         if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) && | 
 | 2021 |                 ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2022 |             ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2023 |                   effectDesc->mDesc.name, effectDesc->mSession); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2024 |             return true; | 
 | 2025 |         } | 
 | 2026 |     } | 
 | 2027 |     return false; | 
 | 2028 | } | 
 | 2029 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2030 | bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2031 | { | 
 | 2032 |     nsecs_t sysTime = systemTime(); | 
 | 2033 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2034 |         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2035 |         if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2036 |             return true; | 
 | 2037 |         } | 
 | 2038 |     } | 
 | 2039 |     return false; | 
 | 2040 | } | 
 | 2041 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2042 | bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2043 |                                                     uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2044 | { | 
 | 2045 |     nsecs_t sysTime = systemTime(); | 
 | 2046 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2047 |         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2048 |         if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2049 |                 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 2050 |             // do not consider re routing (when the output is going to a dynamic policy) | 
 | 2051 |             // as "remote playback" | 
 | 2052 |             if (outputDesc->mPolicyMix == NULL) { | 
| Jean-Michel Trivi | 1767df7 | 2014-12-09 18:11:49 -0800 | [diff] [blame] | 2053 |                 return true; | 
 | 2054 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2055 |         } | 
 | 2056 |     } | 
 | 2057 |     return false; | 
 | 2058 | } | 
 | 2059 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2060 | bool AudioPolicyManager::isSourceActive(audio_source_t source) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2061 | { | 
 | 2062 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2063 |         const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i); | 
| Eric Laurent | a34c9ce | 2014-12-19 11:16:32 -0800 | [diff] [blame] | 2064 |         if (inputDescriptor->mRefCount == 0) { | 
 | 2065 |             continue; | 
 | 2066 |         } | 
 | 2067 |         if (inputDescriptor->mInputSource == (int)source) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2068 |             return true; | 
 | 2069 |         } | 
| Eric Laurent | a34c9ce | 2014-12-19 11:16:32 -0800 | [diff] [blame] | 2070 |         // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it | 
 | 2071 |         // corresponds to an active capture triggered by a hardware hotword recognition | 
 | 2072 |         if ((source == AUDIO_SOURCE_VOICE_RECOGNITION) && | 
 | 2073 |                  (inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD)) { | 
 | 2074 |             // FIXME: we should not assume that the first session is the active one and keep | 
 | 2075 |             // activity count per session. Same in startInput(). | 
 | 2076 |             ssize_t index = mSoundTriggerSessions.indexOfKey(inputDescriptor->mSessions.itemAt(0)); | 
 | 2077 |             if (index >= 0) { | 
 | 2078 |                 return true; | 
 | 2079 |             } | 
 | 2080 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2081 |     } | 
 | 2082 |     return false; | 
 | 2083 | } | 
 | 2084 |  | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 2085 | // Register a list of custom mixes with their attributes and format. | 
 | 2086 | // When a mix is registered, corresponding input and output profiles are | 
 | 2087 | // added to the remote submix hw module. The profile contains only the | 
 | 2088 | // parameters (sampling rate, format...) specified by the mix. | 
 | 2089 | // The corresponding input remote submix device is also connected. | 
 | 2090 | // | 
 | 2091 | // When a remote submix device is connected, the address is checked to select the | 
 | 2092 | // appropriate profile and the corresponding input or output stream is opened. | 
 | 2093 | // | 
 | 2094 | // When capture starts, getInputForAttr() will: | 
 | 2095 | //  - 1 look for a mix matching the address passed in attribtutes tags if any | 
 | 2096 | //  - 2 if none found, getDeviceForInputSource() will: | 
 | 2097 | //     - 2.1 look for a mix matching the attributes source | 
 | 2098 | //     - 2.2 if none found, default to device selection by policy rules | 
 | 2099 | // At this time, the corresponding output remote submix device is also connected | 
 | 2100 | // and active playback use cases can be transferred to this mix if needed when reconnecting | 
 | 2101 | // after AudioTracks are invalidated | 
 | 2102 | // | 
 | 2103 | // When playback starts, getOutputForAttr() will: | 
 | 2104 | //  - 1 look for a mix matching the address passed in attribtutes tags if any | 
 | 2105 | //  - 2 if none found, look for a mix matching the attributes usage | 
 | 2106 | //  - 3 if none found, default to device and output selection by policy rules. | 
 | 2107 |  | 
 | 2108 | status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes) | 
 | 2109 | { | 
 | 2110 |     sp<HwModule> module; | 
 | 2111 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 2112 |         if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 && | 
 | 2113 |                 mHwModules[i]->mHandle != 0) { | 
 | 2114 |             module = mHwModules[i]; | 
 | 2115 |             break; | 
 | 2116 |         } | 
 | 2117 |     } | 
 | 2118 |  | 
 | 2119 |     if (module == 0) { | 
 | 2120 |         return INVALID_OPERATION; | 
 | 2121 |     } | 
 | 2122 |  | 
 | 2123 |     ALOGV("registerPolicyMixes() num mixes %d", mixes.size()); | 
 | 2124 |  | 
 | 2125 |     for (size_t i = 0; i < mixes.size(); i++) { | 
 | 2126 |         String8 address = mixes[i].mRegistrationId; | 
 | 2127 |         ssize_t index = mPolicyMixes.indexOfKey(address); | 
 | 2128 |         if (index >= 0) { | 
 | 2129 |             ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string()); | 
 | 2130 |             continue; | 
 | 2131 |         } | 
 | 2132 |         audio_config_t outputConfig = mixes[i].mFormat; | 
 | 2133 |         audio_config_t inputConfig = mixes[i].mFormat; | 
 | 2134 |         // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in | 
 | 2135 |         // stereo and let audio flinger do the channel conversion if needed. | 
 | 2136 |         outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; | 
 | 2137 |         inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO; | 
 | 2138 |         module->addOutputProfile(address, &outputConfig, | 
 | 2139 |                                  AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address); | 
 | 2140 |         module->addInputProfile(address, &inputConfig, | 
 | 2141 |                                  AUDIO_DEVICE_IN_REMOTE_SUBMIX, address); | 
 | 2142 |         sp<AudioPolicyMix> policyMix = new AudioPolicyMix(); | 
 | 2143 |         policyMix->mMix = mixes[i]; | 
 | 2144 |         mPolicyMixes.add(address, policyMix); | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 2145 |         if (mixes[i].mMixType == MIX_TYPE_PLAYERS) { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 2146 |             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 2147 |                                      AUDIO_POLICY_DEVICE_STATE_AVAILABLE, | 
 | 2148 |                                      address.string()); | 
 | 2149 |         } else { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 2150 |             setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 2151 |                                      AUDIO_POLICY_DEVICE_STATE_AVAILABLE, | 
 | 2152 |                                      address.string()); | 
 | 2153 |         } | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 2154 |     } | 
 | 2155 |     return NO_ERROR; | 
 | 2156 | } | 
 | 2157 |  | 
 | 2158 | status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes) | 
 | 2159 | { | 
 | 2160 |     sp<HwModule> module; | 
 | 2161 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 2162 |         if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 && | 
 | 2163 |                 mHwModules[i]->mHandle != 0) { | 
 | 2164 |             module = mHwModules[i]; | 
 | 2165 |             break; | 
 | 2166 |         } | 
 | 2167 |     } | 
 | 2168 |  | 
 | 2169 |     if (module == 0) { | 
 | 2170 |         return INVALID_OPERATION; | 
 | 2171 |     } | 
 | 2172 |  | 
 | 2173 |     ALOGV("unregisterPolicyMixes() num mixes %d", mixes.size()); | 
 | 2174 |  | 
 | 2175 |     for (size_t i = 0; i < mixes.size(); i++) { | 
 | 2176 |         String8 address = mixes[i].mRegistrationId; | 
 | 2177 |         ssize_t index = mPolicyMixes.indexOfKey(address); | 
 | 2178 |         if (index < 0) { | 
 | 2179 |             ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string()); | 
 | 2180 |             continue; | 
 | 2181 |         } | 
 | 2182 |  | 
 | 2183 |         mPolicyMixes.removeItemsAt(index); | 
 | 2184 |  | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 2185 |         if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) == | 
 | 2186 |                                              AUDIO_POLICY_DEVICE_STATE_AVAILABLE) | 
 | 2187 |         { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 2188 |             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 2189 |                                      AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, | 
 | 2190 |                                      address.string()); | 
 | 2191 |         } | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 2192 |  | 
 | 2193 |         if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) == | 
 | 2194 |                                              AUDIO_POLICY_DEVICE_STATE_AVAILABLE) | 
 | 2195 |         { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 2196 |             setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 2197 |                                      AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, | 
 | 2198 |                                      address.string()); | 
 | 2199 |         } | 
 | 2200 |         module->removeOutputProfile(address); | 
 | 2201 |         module->removeInputProfile(address); | 
 | 2202 |     } | 
 | 2203 |     return NO_ERROR; | 
 | 2204 | } | 
 | 2205 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2206 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2207 | status_t AudioPolicyManager::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2208 | { | 
 | 2209 |     const size_t SIZE = 256; | 
 | 2210 |     char buffer[SIZE]; | 
 | 2211 |     String8 result; | 
 | 2212 |  | 
 | 2213 |     snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this); | 
 | 2214 |     result.append(buffer); | 
 | 2215 |  | 
 | 2216 |     snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput); | 
 | 2217 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2218 |     snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState); | 
 | 2219 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2220 |     snprintf(buffer, SIZE, " Force use for communications %d\n", | 
 | 2221 |              mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2222 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2223 |     snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2224 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2225 |     snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2226 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2227 |     snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2228 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2229 |     snprintf(buffer, SIZE, " Force use for system %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2230 |     result.append(buffer); | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 2231 |     snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n", | 
 | 2232 |             mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]); | 
 | 2233 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2234 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2235 |     snprintf(buffer, SIZE, " Available output devices:\n"); | 
 | 2236 |     result.append(buffer); | 
 | 2237 |     write(fd, result.string(), result.size()); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2238 |     for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2239 |         mAvailableOutputDevices[i]->dump(fd, 2, i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2240 |     } | 
 | 2241 |     snprintf(buffer, SIZE, "\n Available input devices:\n"); | 
 | 2242 |     write(fd, buffer, strlen(buffer)); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2243 |     for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2244 |         mAvailableInputDevices[i]->dump(fd, 2, i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2245 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2246 |  | 
 | 2247 |     snprintf(buffer, SIZE, "\nHW Modules dump:\n"); | 
 | 2248 |     write(fd, buffer, strlen(buffer)); | 
 | 2249 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2250 |         snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2251 |         write(fd, buffer, strlen(buffer)); | 
 | 2252 |         mHwModules[i]->dump(fd); | 
 | 2253 |     } | 
 | 2254 |  | 
 | 2255 |     snprintf(buffer, SIZE, "\nOutputs dump:\n"); | 
 | 2256 |     write(fd, buffer, strlen(buffer)); | 
 | 2257 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2258 |         snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i)); | 
 | 2259 |         write(fd, buffer, strlen(buffer)); | 
 | 2260 |         mOutputs.valueAt(i)->dump(fd); | 
 | 2261 |     } | 
 | 2262 |  | 
 | 2263 |     snprintf(buffer, SIZE, "\nInputs dump:\n"); | 
 | 2264 |     write(fd, buffer, strlen(buffer)); | 
 | 2265 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 2266 |         snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i)); | 
 | 2267 |         write(fd, buffer, strlen(buffer)); | 
 | 2268 |         mInputs.valueAt(i)->dump(fd); | 
 | 2269 |     } | 
 | 2270 |  | 
 | 2271 |     snprintf(buffer, SIZE, "\nStreams dump:\n"); | 
 | 2272 |     write(fd, buffer, strlen(buffer)); | 
 | 2273 |     snprintf(buffer, SIZE, | 
 | 2274 |              " Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n"); | 
 | 2275 |     write(fd, buffer, strlen(buffer)); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2276 |     for (size_t i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2277 |         snprintf(buffer, SIZE, " %02zu      ", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2278 |         write(fd, buffer, strlen(buffer)); | 
 | 2279 |         mStreams[i].dump(fd); | 
 | 2280 |     } | 
 | 2281 |  | 
 | 2282 |     snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n", | 
 | 2283 |             (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory); | 
 | 2284 |     write(fd, buffer, strlen(buffer)); | 
 | 2285 |  | 
 | 2286 |     snprintf(buffer, SIZE, "Registered effects:\n"); | 
 | 2287 |     write(fd, buffer, strlen(buffer)); | 
 | 2288 |     for (size_t i = 0; i < mEffects.size(); i++) { | 
 | 2289 |         snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i)); | 
 | 2290 |         write(fd, buffer, strlen(buffer)); | 
 | 2291 |         mEffects.valueAt(i)->dump(fd); | 
 | 2292 |     } | 
 | 2293 |  | 
| Eric Laurent | 4d41695 | 2014-08-10 14:07:09 -0700 | [diff] [blame] | 2294 |     snprintf(buffer, SIZE, "\nAudio Patches:\n"); | 
 | 2295 |     write(fd, buffer, strlen(buffer)); | 
 | 2296 |     for (size_t i = 0; i < mAudioPatches.size(); i++) { | 
 | 2297 |         mAudioPatches[i]->dump(fd, 2, i); | 
 | 2298 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2299 |  | 
 | 2300 |     return NO_ERROR; | 
 | 2301 | } | 
 | 2302 |  | 
 | 2303 | // This function checks for the parameters which can be offloaded. | 
 | 2304 | // This can be enhanced depending on the capability of the DSP and policy | 
 | 2305 | // of the system. | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2306 | bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadInfo) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2307 | { | 
 | 2308 |     ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d," | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2309 |      " BitRate=%u, duration=%" PRId64 " us, has_video=%d", | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2310 |      offloadInfo.sample_rate, offloadInfo.channel_mask, | 
 | 2311 |      offloadInfo.format, | 
 | 2312 |      offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us, | 
 | 2313 |      offloadInfo.has_video); | 
 | 2314 |  | 
 | 2315 |     // Check if offload has been disabled | 
 | 2316 |     char propValue[PROPERTY_VALUE_MAX]; | 
 | 2317 |     if (property_get("audio.offload.disable", propValue, "0")) { | 
 | 2318 |         if (atoi(propValue) != 0) { | 
 | 2319 |             ALOGV("offload disabled by audio.offload.disable=%s", propValue ); | 
 | 2320 |             return false; | 
 | 2321 |         } | 
 | 2322 |     } | 
 | 2323 |  | 
 | 2324 |     // Check if stream type is music, then only allow offload as of now. | 
 | 2325 |     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC) | 
 | 2326 |     { | 
 | 2327 |         ALOGV("isOffloadSupported: stream_type != MUSIC, returning false"); | 
 | 2328 |         return false; | 
 | 2329 |     } | 
 | 2330 |  | 
 | 2331 |     //TODO: enable audio offloading with video when ready | 
 | 2332 |     if (offloadInfo.has_video) | 
 | 2333 |     { | 
 | 2334 |         ALOGV("isOffloadSupported: has_video == true, returning false"); | 
 | 2335 |         return false; | 
 | 2336 |     } | 
 | 2337 |  | 
 | 2338 |     //If duration is less than minimum value defined in property, return false | 
 | 2339 |     if (property_get("audio.offload.min.duration.secs", propValue, NULL)) { | 
 | 2340 |         if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) { | 
 | 2341 |             ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue); | 
 | 2342 |             return false; | 
 | 2343 |         } | 
 | 2344 |     } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) { | 
 | 2345 |         ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS); | 
 | 2346 |         return false; | 
 | 2347 |     } | 
 | 2348 |  | 
 | 2349 |     // Do not allow offloading if one non offloadable effect is enabled. This prevents from | 
 | 2350 |     // creating an offloaded track and tearing it down immediately after start when audioflinger | 
 | 2351 |     // detects there is an active non offloadable effect. | 
 | 2352 |     // FIXME: We should check the audio session here but we do not have it in this context. | 
 | 2353 |     // This may prevent offloading in rare situations where effects are left active by apps | 
 | 2354 |     // in the background. | 
 | 2355 |     if (isNonOffloadableEffectEnabled()) { | 
 | 2356 |         return false; | 
 | 2357 |     } | 
 | 2358 |  | 
 | 2359 |     // See if there is a profile to support this. | 
 | 2360 |     // AUDIO_DEVICE_NONE | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2361 |     sp<IOProfile> profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2362 |                                             offloadInfo.sample_rate, | 
 | 2363 |                                             offloadInfo.format, | 
 | 2364 |                                             offloadInfo.channel_mask, | 
 | 2365 |                                             AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2366 |     ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT "); | 
 | 2367 |     return (profile != 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2368 | } | 
 | 2369 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2370 | status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role, | 
 | 2371 |                                             audio_port_type_t type, | 
 | 2372 |                                             unsigned int *num_ports, | 
 | 2373 |                                             struct audio_port *ports, | 
 | 2374 |                                             unsigned int *generation) | 
 | 2375 | { | 
 | 2376 |     if (num_ports == NULL || (*num_ports != 0 && ports == NULL) || | 
 | 2377 |             generation == NULL) { | 
 | 2378 |         return BAD_VALUE; | 
 | 2379 |     } | 
 | 2380 |     ALOGV("listAudioPorts() role %d type %d num_ports %d ports %p", role, type, *num_ports, ports); | 
 | 2381 |     if (ports == NULL) { | 
 | 2382 |         *num_ports = 0; | 
 | 2383 |     } | 
 | 2384 |  | 
 | 2385 |     size_t portsWritten = 0; | 
 | 2386 |     size_t portsMax = *num_ports; | 
 | 2387 |     *num_ports = 0; | 
 | 2388 |     if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2389 |         if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) { | 
 | 2390 |             for (size_t i = 0; | 
 | 2391 |                     i  < mAvailableOutputDevices.size() && portsWritten < portsMax; i++) { | 
 | 2392 |                 mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]); | 
 | 2393 |             } | 
 | 2394 |             *num_ports += mAvailableOutputDevices.size(); | 
 | 2395 |         } | 
 | 2396 |         if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) { | 
 | 2397 |             for (size_t i = 0; | 
 | 2398 |                     i  < mAvailableInputDevices.size() && portsWritten < portsMax; i++) { | 
 | 2399 |                 mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]); | 
 | 2400 |             } | 
 | 2401 |             *num_ports += mAvailableInputDevices.size(); | 
 | 2402 |         } | 
 | 2403 |     } | 
 | 2404 |     if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_MIX) { | 
 | 2405 |         if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) { | 
 | 2406 |             for (size_t i = 0; i < mInputs.size() && portsWritten < portsMax; i++) { | 
 | 2407 |                 mInputs[i]->toAudioPort(&ports[portsWritten++]); | 
 | 2408 |             } | 
 | 2409 |             *num_ports += mInputs.size(); | 
 | 2410 |         } | 
 | 2411 |         if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2412 |             size_t numOutputs = 0; | 
 | 2413 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2414 |                 if (!mOutputs[i]->isDuplicated()) { | 
 | 2415 |                     numOutputs++; | 
 | 2416 |                     if (portsWritten < portsMax) { | 
 | 2417 |                         mOutputs[i]->toAudioPort(&ports[portsWritten++]); | 
 | 2418 |                     } | 
 | 2419 |                 } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2420 |             } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2421 |             *num_ports += numOutputs; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2422 |         } | 
 | 2423 |     } | 
 | 2424 |     *generation = curAudioPortGeneration(); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2425 |     ALOGV("listAudioPorts() got %zu ports needed %d", portsWritten, *num_ports); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2426 |     return NO_ERROR; | 
 | 2427 | } | 
 | 2428 |  | 
 | 2429 | status_t AudioPolicyManager::getAudioPort(struct audio_port *port __unused) | 
 | 2430 | { | 
 | 2431 |     return NO_ERROR; | 
 | 2432 | } | 
 | 2433 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2434 | sp<AudioPolicyManager::AudioOutputDescriptor> AudioPolicyManager::getOutputFromId( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2435 |                                                                     audio_port_handle_t id) const | 
 | 2436 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2437 |     sp<AudioOutputDescriptor> outputDesc = NULL; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2438 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2439 |         outputDesc = mOutputs.valueAt(i); | 
 | 2440 |         if (outputDesc->mId == id) { | 
 | 2441 |             break; | 
 | 2442 |         } | 
 | 2443 |     } | 
 | 2444 |     return outputDesc; | 
 | 2445 | } | 
 | 2446 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2447 | sp<AudioPolicyManager::AudioInputDescriptor> AudioPolicyManager::getInputFromId( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2448 |                                                                     audio_port_handle_t id) const | 
 | 2449 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2450 |     sp<AudioInputDescriptor> inputDesc = NULL; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2451 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 2452 |         inputDesc = mInputs.valueAt(i); | 
 | 2453 |         if (inputDesc->mId == id) { | 
 | 2454 |             break; | 
 | 2455 |         } | 
 | 2456 |     } | 
 | 2457 |     return inputDesc; | 
 | 2458 | } | 
 | 2459 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2460 | sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleForDevice( | 
 | 2461 |                                                                     audio_devices_t device) const | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2462 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2463 |     sp <HwModule> module; | 
 | 2464 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2465 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 2466 |         if (mHwModules[i]->mHandle == 0) { | 
 | 2467 |             continue; | 
 | 2468 |         } | 
 | 2469 |         if (audio_is_output_device(device)) { | 
 | 2470 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2471 |             { | 
 | 2472 |                 if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) { | 
 | 2473 |                     return mHwModules[i]; | 
 | 2474 |                 } | 
 | 2475 |             } | 
 | 2476 |         } else { | 
 | 2477 |             for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) { | 
 | 2478 |                 if (mHwModules[i]->mInputProfiles[j]->mSupportedDevices.types() & | 
 | 2479 |                         device & ~AUDIO_DEVICE_BIT_IN) { | 
 | 2480 |                     return mHwModules[i]; | 
 | 2481 |                 } | 
 | 2482 |             } | 
 | 2483 |         } | 
 | 2484 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2485 |     return module; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2486 | } | 
 | 2487 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2488 | sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleFromName(const char *name) const | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2489 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2490 |     sp <HwModule> module; | 
 | 2491 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2492 |     for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 2493 |     { | 
 | 2494 |         if (strcmp(mHwModules[i]->mName, name) == 0) { | 
 | 2495 |             return mHwModules[i]; | 
 | 2496 |         } | 
 | 2497 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2498 |     return module; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2499 | } | 
 | 2500 |  | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 2501 | audio_devices_t AudioPolicyManager::availablePrimaryOutputDevices() | 
 | 2502 | { | 
 | 2503 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
 | 2504 |     audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types(); | 
 | 2505 |     return devices & mAvailableOutputDevices.types(); | 
 | 2506 | } | 
 | 2507 |  | 
 | 2508 | audio_devices_t AudioPolicyManager::availablePrimaryInputDevices() | 
 | 2509 | { | 
 | 2510 |     audio_module_handle_t primaryHandle = | 
 | 2511 |                                 mOutputs.valueFor(mPrimaryOutput)->mProfile->mModule->mHandle; | 
 | 2512 |     audio_devices_t devices = AUDIO_DEVICE_NONE; | 
 | 2513 |     for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { | 
 | 2514 |         if (mAvailableInputDevices[i]->mModule->mHandle == primaryHandle) { | 
 | 2515 |             devices |= mAvailableInputDevices[i]->mDeviceType; | 
 | 2516 |         } | 
 | 2517 |     } | 
 | 2518 |     return devices; | 
 | 2519 | } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2520 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2521 | status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, | 
 | 2522 |                                                audio_patch_handle_t *handle, | 
 | 2523 |                                                uid_t uid) | 
 | 2524 | { | 
 | 2525 |     ALOGV("createAudioPatch()"); | 
 | 2526 |  | 
 | 2527 |     if (handle == NULL || patch == NULL) { | 
 | 2528 |         return BAD_VALUE; | 
 | 2529 |     } | 
 | 2530 |     ALOGV("createAudioPatch() num sources %d num sinks %d", patch->num_sources, patch->num_sinks); | 
 | 2531 |  | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2532 |     if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || | 
 | 2533 |             patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { | 
 | 2534 |         return BAD_VALUE; | 
 | 2535 |     } | 
 | 2536 |     // only one source per audio patch supported for now | 
 | 2537 |     if (patch->num_sources > 1) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2538 |         return INVALID_OPERATION; | 
 | 2539 |     } | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2540 |  | 
 | 2541 |     if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2542 |         return INVALID_OPERATION; | 
 | 2543 |     } | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2544 |     for (size_t i = 0; i < patch->num_sinks; i++) { | 
 | 2545 |         if (patch->sinks[i].role != AUDIO_PORT_ROLE_SINK) { | 
 | 2546 |             return INVALID_OPERATION; | 
 | 2547 |         } | 
 | 2548 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2549 |  | 
 | 2550 |     sp<AudioPatch> patchDesc; | 
 | 2551 |     ssize_t index = mAudioPatches.indexOfKey(*handle); | 
 | 2552 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2553 |     ALOGV("createAudioPatch source id %d role %d type %d", patch->sources[0].id, | 
 | 2554 |                                                            patch->sources[0].role, | 
 | 2555 |                                                            patch->sources[0].type); | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2556 | #if LOG_NDEBUG == 0 | 
 | 2557 |     for (size_t i = 0; i < patch->num_sinks; i++) { | 
 | 2558 |         ALOGV("createAudioPatch sink %d: id %d role %d type %d", i, patch->sinks[i].id, | 
 | 2559 |                                                              patch->sinks[i].role, | 
 | 2560 |                                                              patch->sinks[i].type); | 
 | 2561 |     } | 
 | 2562 | #endif | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2563 |  | 
 | 2564 |     if (index >= 0) { | 
 | 2565 |         patchDesc = mAudioPatches.valueAt(index); | 
 | 2566 |         ALOGV("createAudioPatch() mUidCached %d patchDesc->mUid %d uid %d", | 
 | 2567 |                                                                   mUidCached, patchDesc->mUid, uid); | 
 | 2568 |         if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) { | 
 | 2569 |             return INVALID_OPERATION; | 
 | 2570 |         } | 
 | 2571 |     } else { | 
 | 2572 |         *handle = 0; | 
 | 2573 |     } | 
 | 2574 |  | 
 | 2575 |     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2576 |         sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2577 |         if (outputDesc == NULL) { | 
 | 2578 |             ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id); | 
 | 2579 |             return BAD_VALUE; | 
 | 2580 |         } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2581 |         ALOG_ASSERT(!outputDesc->isDuplicated(),"duplicated output %d in source in ports", | 
 | 2582 |                                                 outputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2583 |         if (patchDesc != 0) { | 
 | 2584 |             if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) { | 
 | 2585 |                 ALOGV("createAudioPatch() source id differs for patch current id %d new id %d", | 
 | 2586 |                                           patchDesc->mPatch.sources[0].id, patch->sources[0].id); | 
 | 2587 |                 return BAD_VALUE; | 
 | 2588 |             } | 
 | 2589 |         } | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2590 |         DeviceVector devices; | 
 | 2591 |         for (size_t i = 0; i < patch->num_sinks; i++) { | 
 | 2592 |             // Only support mix to devices connection | 
 | 2593 |             // TODO add support for mix to mix connection | 
 | 2594 |             if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { | 
 | 2595 |                 ALOGV("createAudioPatch() source mix but sink is not a device"); | 
 | 2596 |                 return INVALID_OPERATION; | 
 | 2597 |             } | 
 | 2598 |             sp<DeviceDescriptor> devDesc = | 
 | 2599 |                     mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id); | 
 | 2600 |             if (devDesc == 0) { | 
 | 2601 |                 ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[i].id); | 
 | 2602 |                 return BAD_VALUE; | 
 | 2603 |             } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2604 |  | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2605 |             if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType, | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 2606 |                                                            devDesc->mAddress, | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2607 |                                                            patch->sources[0].sample_rate, | 
 | 2608 |                                                          NULL,  // updatedSamplingRate | 
 | 2609 |                                                          patch->sources[0].format, | 
 | 2610 |                                                          patch->sources[0].channel_mask, | 
 | 2611 |                                                          AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) { | 
 | 2612 |                 ALOGV("createAudioPatch() profile not supported for device %08x", | 
 | 2613 |                       devDesc->mDeviceType); | 
 | 2614 |                 return INVALID_OPERATION; | 
 | 2615 |             } | 
 | 2616 |             devices.add(devDesc); | 
 | 2617 |         } | 
 | 2618 |         if (devices.size() == 0) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2619 |             return INVALID_OPERATION; | 
 | 2620 |         } | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2621 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2622 |         // TODO: reconfigure output format and channels here | 
 | 2623 |         ALOGV("createAudioPatch() setting device %08x on output %d", | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2624 |               devices.types(), outputDesc->mIoHandle); | 
 | 2625 |         setOutputDevice(outputDesc->mIoHandle, devices.types(), true, 0, handle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2626 |         index = mAudioPatches.indexOfKey(*handle); | 
 | 2627 |         if (index >= 0) { | 
 | 2628 |             if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { | 
 | 2629 |                 ALOGW("createAudioPatch() setOutputDevice() did not reuse the patch provided"); | 
 | 2630 |             } | 
 | 2631 |             patchDesc = mAudioPatches.valueAt(index); | 
 | 2632 |             patchDesc->mUid = uid; | 
 | 2633 |             ALOGV("createAudioPatch() success"); | 
 | 2634 |         } else { | 
 | 2635 |             ALOGW("createAudioPatch() setOutputDevice() failed to create a patch"); | 
 | 2636 |             return INVALID_OPERATION; | 
 | 2637 |         } | 
 | 2638 |     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2639 |         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { | 
 | 2640 |             // input device to input mix connection | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2641 |             // only one sink supported when connecting an input device to a mix | 
 | 2642 |             if (patch->num_sinks > 1) { | 
 | 2643 |                 return INVALID_OPERATION; | 
 | 2644 |             } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2645 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2646 |             if (inputDesc == NULL) { | 
 | 2647 |                 return BAD_VALUE; | 
 | 2648 |             } | 
 | 2649 |             if (patchDesc != 0) { | 
 | 2650 |                 if (patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { | 
 | 2651 |                     return BAD_VALUE; | 
 | 2652 |                 } | 
 | 2653 |             } | 
 | 2654 |             sp<DeviceDescriptor> devDesc = | 
 | 2655 |                     mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); | 
 | 2656 |             if (devDesc == 0) { | 
 | 2657 |                 return BAD_VALUE; | 
 | 2658 |             } | 
 | 2659 |  | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2660 |             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType, | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 2661 |                                                           devDesc->mAddress, | 
 | 2662 |                                                           patch->sinks[0].sample_rate, | 
 | 2663 |                                                           NULL, /*updatedSampleRate*/ | 
 | 2664 |                                                           patch->sinks[0].format, | 
 | 2665 |                                                           patch->sinks[0].channel_mask, | 
 | 2666 |                                                           // FIXME for the parameter type, | 
 | 2667 |                                                           // and the NONE | 
 | 2668 |                                                           (audio_output_flags_t) | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 2669 |                                                             AUDIO_INPUT_FLAG_NONE)) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2670 |                 return INVALID_OPERATION; | 
 | 2671 |             } | 
 | 2672 |             // TODO: reconfigure output format and channels here | 
 | 2673 |             ALOGV("createAudioPatch() setting device %08x on output %d", | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2674 |                                                   devDesc->mDeviceType, inputDesc->mIoHandle); | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2675 |             setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2676 |             index = mAudioPatches.indexOfKey(*handle); | 
 | 2677 |             if (index >= 0) { | 
 | 2678 |                 if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { | 
 | 2679 |                     ALOGW("createAudioPatch() setInputDevice() did not reuse the patch provided"); | 
 | 2680 |                 } | 
 | 2681 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 2682 |                 patchDesc->mUid = uid; | 
 | 2683 |                 ALOGV("createAudioPatch() success"); | 
 | 2684 |             } else { | 
 | 2685 |                 ALOGW("createAudioPatch() setInputDevice() failed to create a patch"); | 
 | 2686 |                 return INVALID_OPERATION; | 
 | 2687 |             } | 
 | 2688 |         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2689 |             // device to device connection | 
 | 2690 |             if (patchDesc != 0) { | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2691 |                 if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2692 |                     return BAD_VALUE; | 
 | 2693 |                 } | 
 | 2694 |             } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2695 |             sp<DeviceDescriptor> srcDeviceDesc = | 
 | 2696 |                     mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); | 
| Eric Laurent | 58f8eb7 | 2014-09-12 16:19:41 -0700 | [diff] [blame] | 2697 |             if (srcDeviceDesc == 0) { | 
 | 2698 |                 return BAD_VALUE; | 
 | 2699 |             } | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2700 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2701 |             //update source and sink with our own data as the data passed in the patch may | 
 | 2702 |             // be incomplete. | 
 | 2703 |             struct audio_patch newPatch = *patch; | 
 | 2704 |             srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2705 |  | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2706 |             for (size_t i = 0; i < patch->num_sinks; i++) { | 
 | 2707 |                 if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { | 
 | 2708 |                     ALOGV("createAudioPatch() source device but one sink is not a device"); | 
 | 2709 |                     return INVALID_OPERATION; | 
 | 2710 |                 } | 
 | 2711 |  | 
 | 2712 |                 sp<DeviceDescriptor> sinkDeviceDesc = | 
 | 2713 |                         mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id); | 
 | 2714 |                 if (sinkDeviceDesc == 0) { | 
 | 2715 |                     return BAD_VALUE; | 
 | 2716 |                 } | 
 | 2717 |                 sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]); | 
 | 2718 |  | 
 | 2719 |                 if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) { | 
 | 2720 |                     // only one sink supported when connected devices across HW modules | 
 | 2721 |                     if (patch->num_sinks > 1) { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2722 |                         return INVALID_OPERATION; | 
 | 2723 |                     } | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2724 |                     SortedVector<audio_io_handle_t> outputs = | 
 | 2725 |                                             getOutputsForDevice(sinkDeviceDesc->mDeviceType, | 
 | 2726 |                                                                 mOutputs); | 
 | 2727 |                     // if the sink device is reachable via an opened output stream, request to go via | 
 | 2728 |                     // this output stream by adding a second source to the patch description | 
| Eric Laurent | 8838a38 | 2014-09-08 16:44:28 -0700 | [diff] [blame] | 2729 |                     audio_io_handle_t output = selectOutput(outputs, | 
 | 2730 |                                                             AUDIO_OUTPUT_FLAG_NONE, | 
 | 2731 |                                                             AUDIO_FORMAT_INVALID); | 
| Eric Laurent | 874c4287 | 2014-08-08 15:13:39 -0700 | [diff] [blame] | 2732 |                     if (output != AUDIO_IO_HANDLE_NONE) { | 
 | 2733 |                         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
 | 2734 |                         if (outputDesc->isDuplicated()) { | 
 | 2735 |                             return INVALID_OPERATION; | 
 | 2736 |                         } | 
 | 2737 |                         outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]); | 
 | 2738 |                         newPatch.num_sources = 2; | 
 | 2739 |                     } | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2740 |                 } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2741 |             } | 
 | 2742 |             // TODO: check from routing capabilities in config file and other conflicting patches | 
 | 2743 |  | 
 | 2744 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 2745 |             if (index >= 0) { | 
 | 2746 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 2747 |             } | 
 | 2748 |  | 
 | 2749 |             status_t status = mpClientInterface->createAudioPatch(&newPatch, | 
 | 2750 |                                                                   &afPatchHandle, | 
 | 2751 |                                                                   0); | 
 | 2752 |             ALOGV("createAudioPatch() patch panel returned %d patchHandle %d", | 
 | 2753 |                                                                   status, afPatchHandle); | 
 | 2754 |             if (status == NO_ERROR) { | 
 | 2755 |                 if (index < 0) { | 
 | 2756 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 2757 |                                                &newPatch, uid); | 
 | 2758 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 2759 |                 } else { | 
 | 2760 |                     patchDesc->mPatch = newPatch; | 
 | 2761 |                 } | 
 | 2762 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 2763 |                 *handle = patchDesc->mHandle; | 
 | 2764 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 2765 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2766 |             } else { | 
 | 2767 |                 ALOGW("createAudioPatch() patch panel could not connect device patch, error %d", | 
 | 2768 |                 status); | 
 | 2769 |                 return INVALID_OPERATION; | 
 | 2770 |             } | 
 | 2771 |         } else { | 
 | 2772 |             return BAD_VALUE; | 
 | 2773 |         } | 
 | 2774 |     } else { | 
 | 2775 |         return BAD_VALUE; | 
 | 2776 |     } | 
 | 2777 |     return NO_ERROR; | 
 | 2778 | } | 
 | 2779 |  | 
 | 2780 | status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle, | 
 | 2781 |                                                   uid_t uid) | 
 | 2782 | { | 
 | 2783 |     ALOGV("releaseAudioPatch() patch %d", handle); | 
 | 2784 |  | 
 | 2785 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2786 |  | 
 | 2787 |     if (index < 0) { | 
 | 2788 |         return BAD_VALUE; | 
 | 2789 |     } | 
 | 2790 |     sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 2791 |     ALOGV("releaseAudioPatch() mUidCached %d patchDesc->mUid %d uid %d", | 
 | 2792 |           mUidCached, patchDesc->mUid, uid); | 
 | 2793 |     if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) { | 
 | 2794 |         return INVALID_OPERATION; | 
 | 2795 |     } | 
 | 2796 |  | 
 | 2797 |     struct audio_patch *patch = &patchDesc->mPatch; | 
 | 2798 |     patchDesc->mUid = mUidCached; | 
 | 2799 |     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2800 |         sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2801 |         if (outputDesc == NULL) { | 
 | 2802 |             ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id); | 
 | 2803 |             return BAD_VALUE; | 
 | 2804 |         } | 
 | 2805 |  | 
 | 2806 |         setOutputDevice(outputDesc->mIoHandle, | 
 | 2807 |                         getNewOutputDevice(outputDesc->mIoHandle, true /*fromCache*/), | 
 | 2808 |                        true, | 
 | 2809 |                        0, | 
 | 2810 |                        NULL); | 
 | 2811 |     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2812 |         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2813 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2814 |             if (inputDesc == NULL) { | 
 | 2815 |                 ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id); | 
 | 2816 |                 return BAD_VALUE; | 
 | 2817 |             } | 
 | 2818 |             setInputDevice(inputDesc->mIoHandle, | 
 | 2819 |                            getNewInputDevice(inputDesc->mIoHandle), | 
 | 2820 |                            true, | 
 | 2821 |                            NULL); | 
 | 2822 |         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2823 |             audio_patch_handle_t afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 2824 |             status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
 | 2825 |             ALOGV("releaseAudioPatch() patch panel returned %d patchHandle %d", | 
 | 2826 |                                                               status, patchDesc->mAfPatchHandle); | 
 | 2827 |             removeAudioPatch(patchDesc->mHandle); | 
 | 2828 |             nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 2829 |             mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2830 |         } else { | 
 | 2831 |             return BAD_VALUE; | 
 | 2832 |         } | 
 | 2833 |     } else { | 
 | 2834 |         return BAD_VALUE; | 
 | 2835 |     } | 
 | 2836 |     return NO_ERROR; | 
 | 2837 | } | 
 | 2838 |  | 
 | 2839 | status_t AudioPolicyManager::listAudioPatches(unsigned int *num_patches, | 
 | 2840 |                                               struct audio_patch *patches, | 
 | 2841 |                                               unsigned int *generation) | 
 | 2842 | { | 
 | 2843 |     if (num_patches == NULL || (*num_patches != 0 && patches == NULL) || | 
 | 2844 |             generation == NULL) { | 
 | 2845 |         return BAD_VALUE; | 
 | 2846 |     } | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2847 |     ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2848 |           *num_patches, patches, mAudioPatches.size()); | 
 | 2849 |     if (patches == NULL) { | 
 | 2850 |         *num_patches = 0; | 
 | 2851 |     } | 
 | 2852 |  | 
 | 2853 |     size_t patchesWritten = 0; | 
 | 2854 |     size_t patchesMax = *num_patches; | 
 | 2855 |     for (size_t i = 0; | 
 | 2856 |             i  < mAudioPatches.size() && patchesWritten < patchesMax; i++) { | 
 | 2857 |         patches[patchesWritten] = mAudioPatches[i]->mPatch; | 
 | 2858 |         patches[patchesWritten++].id = mAudioPatches[i]->mHandle; | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2859 |         ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2860 |               i, mAudioPatches[i]->mPatch.num_sources, mAudioPatches[i]->mPatch.num_sinks); | 
 | 2861 |     } | 
 | 2862 |     *num_patches = mAudioPatches.size(); | 
 | 2863 |  | 
 | 2864 |     *generation = curAudioPortGeneration(); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2865 |     ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2866 |     return NO_ERROR; | 
 | 2867 | } | 
 | 2868 |  | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2869 | status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config) | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2870 | { | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2871 |     ALOGV("setAudioPortConfig()"); | 
 | 2872 |  | 
 | 2873 |     if (config == NULL) { | 
 | 2874 |         return BAD_VALUE; | 
 | 2875 |     } | 
 | 2876 |     ALOGV("setAudioPortConfig() on port handle %d", config->id); | 
 | 2877 |     // Only support gain configuration for now | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2878 |     if (config->config_mask != AUDIO_PORT_CONFIG_GAIN) { | 
 | 2879 |         return INVALID_OPERATION; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2880 |     } | 
 | 2881 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2882 |     sp<AudioPortConfig> audioPortConfig; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2883 |     if (config->type == AUDIO_PORT_TYPE_MIX) { | 
 | 2884 |         if (config->role == AUDIO_PORT_ROLE_SOURCE) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2885 |             sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2886 |             if (outputDesc == NULL) { | 
 | 2887 |                 return BAD_VALUE; | 
 | 2888 |             } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2889 |             ALOG_ASSERT(!outputDesc->isDuplicated(), | 
 | 2890 |                         "setAudioPortConfig() called on duplicated output %d", | 
 | 2891 |                         outputDesc->mIoHandle); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2892 |             audioPortConfig = outputDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2893 |         } else if (config->role == AUDIO_PORT_ROLE_SINK) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2894 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2895 |             if (inputDesc == NULL) { | 
 | 2896 |                 return BAD_VALUE; | 
 | 2897 |             } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2898 |             audioPortConfig = inputDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2899 |         } else { | 
 | 2900 |             return BAD_VALUE; | 
 | 2901 |         } | 
 | 2902 |     } else if (config->type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2903 |         sp<DeviceDescriptor> deviceDesc; | 
 | 2904 |         if (config->role == AUDIO_PORT_ROLE_SOURCE) { | 
 | 2905 |             deviceDesc = mAvailableInputDevices.getDeviceFromId(config->id); | 
 | 2906 |         } else if (config->role == AUDIO_PORT_ROLE_SINK) { | 
 | 2907 |             deviceDesc = mAvailableOutputDevices.getDeviceFromId(config->id); | 
 | 2908 |         } else { | 
 | 2909 |             return BAD_VALUE; | 
 | 2910 |         } | 
 | 2911 |         if (deviceDesc == NULL) { | 
 | 2912 |             return BAD_VALUE; | 
 | 2913 |         } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2914 |         audioPortConfig = deviceDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2915 |     } else { | 
 | 2916 |         return BAD_VALUE; | 
 | 2917 |     } | 
 | 2918 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2919 |     struct audio_port_config backupConfig; | 
 | 2920 |     status_t status = audioPortConfig->applyAudioPortConfig(config, &backupConfig); | 
 | 2921 |     if (status == NO_ERROR) { | 
 | 2922 |         struct audio_port_config newConfig; | 
 | 2923 |         audioPortConfig->toAudioPortConfig(&newConfig, config); | 
 | 2924 |         status = mpClientInterface->setAudioPortConfig(&newConfig, 0); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2925 |     } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2926 |     if (status != NO_ERROR) { | 
 | 2927 |         audioPortConfig->applyAudioPortConfig(&backupConfig); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2928 |     } | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2929 |  | 
 | 2930 |     return status; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2931 | } | 
 | 2932 |  | 
 | 2933 | void AudioPolicyManager::clearAudioPatches(uid_t uid) | 
 | 2934 | { | 
| Eric Laurent | 0add0fd | 2014-12-04 18:58:14 -0800 | [diff] [blame] | 2935 |     for (ssize_t i = (ssize_t)mAudioPatches.size() - 1; i >= 0; i--)  { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2936 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(i); | 
 | 2937 |         if (patchDesc->mUid == uid) { | 
| Eric Laurent | 0add0fd | 2014-12-04 18:58:14 -0800 | [diff] [blame] | 2938 |             releaseAudioPatch(mAudioPatches.keyAt(i), uid); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2939 |         } | 
 | 2940 |     } | 
 | 2941 | } | 
 | 2942 |  | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 2943 | status_t AudioPolicyManager::acquireSoundTriggerSession(audio_session_t *session, | 
 | 2944 |                                        audio_io_handle_t *ioHandle, | 
 | 2945 |                                        audio_devices_t *device) | 
 | 2946 | { | 
 | 2947 |     *session = (audio_session_t)mpClientInterface->newAudioUniqueId(); | 
 | 2948 |     *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId(); | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 2949 |     *device = getDeviceAndMixForInputSource(AUDIO_SOURCE_HOTWORD); | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 2950 |  | 
 | 2951 |     mSoundTriggerSessions.add(*session, *ioHandle); | 
 | 2952 |  | 
 | 2953 |     return NO_ERROR; | 
 | 2954 | } | 
 | 2955 |  | 
 | 2956 | status_t AudioPolicyManager::releaseSoundTriggerSession(audio_session_t session) | 
 | 2957 | { | 
 | 2958 |     ssize_t index = mSoundTriggerSessions.indexOfKey(session); | 
 | 2959 |     if (index < 0) { | 
 | 2960 |         ALOGW("acquireSoundTriggerSession() session %d not registered", session); | 
 | 2961 |         return BAD_VALUE; | 
 | 2962 |     } | 
 | 2963 |  | 
 | 2964 |     mSoundTriggerSessions.removeItem(session); | 
 | 2965 |     return NO_ERROR; | 
 | 2966 | } | 
 | 2967 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2968 | status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle, | 
 | 2969 |                                            const sp<AudioPatch>& patch) | 
 | 2970 | { | 
 | 2971 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2972 |  | 
 | 2973 |     if (index >= 0) { | 
 | 2974 |         ALOGW("addAudioPatch() patch %d already in", handle); | 
 | 2975 |         return ALREADY_EXISTS; | 
 | 2976 |     } | 
 | 2977 |     mAudioPatches.add(handle, patch); | 
 | 2978 |     ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d" | 
 | 2979 |             "sink handle %d", | 
 | 2980 |           handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks, | 
 | 2981 |           patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id); | 
 | 2982 |     return NO_ERROR; | 
 | 2983 | } | 
 | 2984 |  | 
 | 2985 | status_t AudioPolicyManager::removeAudioPatch(audio_patch_handle_t handle) | 
 | 2986 | { | 
 | 2987 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2988 |  | 
 | 2989 |     if (index < 0) { | 
 | 2990 |         ALOGW("removeAudioPatch() patch %d not in", handle); | 
 | 2991 |         return ALREADY_EXISTS; | 
 | 2992 |     } | 
 | 2993 |     ALOGV("removeAudioPatch() handle %d af handle %d", handle, | 
 | 2994 |                       mAudioPatches.valueAt(index)->mAfPatchHandle); | 
 | 2995 |     mAudioPatches.removeItemsAt(index); | 
 | 2996 |     return NO_ERROR; | 
 | 2997 | } | 
 | 2998 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2999 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3000 | // AudioPolicyManager | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3001 | // ---------------------------------------------------------------------------- | 
 | 3002 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3003 | uint32_t AudioPolicyManager::nextUniqueId() | 
 | 3004 | { | 
 | 3005 |     return android_atomic_inc(&mNextUniqueId); | 
 | 3006 | } | 
 | 3007 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3008 | uint32_t AudioPolicyManager::nextAudioPortGeneration() | 
 | 3009 | { | 
 | 3010 |     return android_atomic_inc(&mAudioPortGeneration); | 
 | 3011 | } | 
 | 3012 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3013 | AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3014 |     : | 
 | 3015 | #ifdef AUDIO_POLICY_TEST | 
 | 3016 |     Thread(false), | 
 | 3017 | #endif //AUDIO_POLICY_TEST | 
 | 3018 |     mPrimaryOutput((audio_io_handle_t)0), | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3019 |     mPhoneState(AUDIO_MODE_NORMAL), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3020 |     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), | 
 | 3021 |     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3022 |     mA2dpSuspended(false), | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3023 |     mSpeakerDrcEnabled(false), mNextUniqueId(1), | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 3024 |     mAudioPortGeneration(1), | 
 | 3025 |     mBeaconMuteRefCount(0), | 
 | 3026 |     mBeaconPlayingRefCount(0), | 
 | 3027 |     mBeaconMuted(false) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3028 | { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3029 |     mUidCached = getuid(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3030 |     mpClientInterface = clientInterface; | 
 | 3031 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3032 |     for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) { | 
 | 3033 |         mForceUse[i] = AUDIO_POLICY_FORCE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3034 |     } | 
 | 3035 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 3036 |     mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3037 |     if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) { | 
 | 3038 |         if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { | 
 | 3039 |             ALOGE("could not load audio policy configuration file, setting defaults"); | 
 | 3040 |             defaultAudioPolicyConfig(); | 
 | 3041 |         } | 
 | 3042 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3043 |     // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3044 |  | 
 | 3045 |     // must be done after reading the policy | 
 | 3046 |     initializeVolumeCurves(); | 
 | 3047 |  | 
 | 3048 |     // open all output streams needed to access attached devices | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3049 |     audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types(); | 
 | 3050 |     audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3051 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 3052 |         mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName); | 
 | 3053 |         if (mHwModules[i]->mHandle == 0) { | 
 | 3054 |             ALOGW("could not open HW module %s", mHwModules[i]->mName); | 
 | 3055 |             continue; | 
 | 3056 |         } | 
 | 3057 |         // open all output streams needed to access attached devices | 
 | 3058 |         // except for direct output streams that are only opened when they are actually | 
 | 3059 |         // required by an app. | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3060 |         // This also validates mAvailableOutputDevices list | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3061 |         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 3062 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3063 |             const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3064 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3065 |             if (outProfile->mSupportedDevices.isEmpty()) { | 
 | 3066 |                 ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName); | 
 | 3067 |                 continue; | 
 | 3068 |             } | 
 | 3069 |  | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3070 |             if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) { | 
 | 3071 |                 continue; | 
 | 3072 |             } | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 3073 |             audio_devices_t profileType = outProfile->mSupportedDevices.types(); | 
 | 3074 |             if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) { | 
 | 3075 |                 profileType = mDefaultOutputDevice->mDeviceType; | 
 | 3076 |             } else { | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3077 |                 // chose first device present in mSupportedDevices also part of | 
 | 3078 |                 // outputDeviceTypes | 
 | 3079 |                 for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) { | 
 | 3080 |                     profileType = outProfile->mSupportedDevices[k]->mDeviceType; | 
 | 3081 |                     if ((profileType & outputDeviceTypes) != 0) { | 
 | 3082 |                         break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3083 |                     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3084 |                 } | 
 | 3085 |             } | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3086 |             if ((profileType & outputDeviceTypes) == 0) { | 
 | 3087 |                 continue; | 
 | 3088 |             } | 
 | 3089 |             sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile); | 
 | 3090 |  | 
 | 3091 |             outputDesc->mDevice = profileType; | 
 | 3092 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 3093 |             config.sample_rate = outputDesc->mSamplingRate; | 
 | 3094 |             config.channel_mask = outputDesc->mChannelMask; | 
 | 3095 |             config.format = outputDesc->mFormat; | 
 | 3096 |             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; | 
 | 3097 |             status_t status = mpClientInterface->openOutput(outProfile->mModule->mHandle, | 
 | 3098 |                                                             &output, | 
 | 3099 |                                                             &config, | 
 | 3100 |                                                             &outputDesc->mDevice, | 
 | 3101 |                                                             String8(""), | 
 | 3102 |                                                             &outputDesc->mLatency, | 
 | 3103 |                                                             outputDesc->mFlags); | 
 | 3104 |  | 
 | 3105 |             if (status != NO_ERROR) { | 
 | 3106 |                 ALOGW("Cannot open output stream for device %08x on hw module %s", | 
 | 3107 |                       outputDesc->mDevice, | 
 | 3108 |                       mHwModules[i]->mName); | 
 | 3109 |             } else { | 
 | 3110 |                 outputDesc->mSamplingRate = config.sample_rate; | 
 | 3111 |                 outputDesc->mChannelMask = config.channel_mask; | 
 | 3112 |                 outputDesc->mFormat = config.format; | 
 | 3113 |  | 
 | 3114 |                 for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) { | 
 | 3115 |                     audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType; | 
 | 3116 |                     ssize_t index = | 
 | 3117 |                             mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]); | 
 | 3118 |                     // give a valid ID to an attached device once confirmed it is reachable | 
 | 3119 |                     if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) { | 
 | 3120 |                         mAvailableOutputDevices[index]->mId = nextUniqueId(); | 
 | 3121 |                         mAvailableOutputDevices[index]->mModule = mHwModules[i]; | 
 | 3122 |                     } | 
 | 3123 |                 } | 
 | 3124 |                 if (mPrimaryOutput == 0 && | 
 | 3125 |                         outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { | 
 | 3126 |                     mPrimaryOutput = output; | 
 | 3127 |                 } | 
 | 3128 |                 addOutput(output, outputDesc); | 
 | 3129 |                 setOutputDevice(output, | 
 | 3130 |                                 outputDesc->mDevice, | 
 | 3131 |                                 true); | 
 | 3132 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3133 |         } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3134 |         // open input streams needed to access attached devices to validate | 
 | 3135 |         // mAvailableInputDevices list | 
 | 3136 |         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) | 
 | 3137 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3138 |             const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3139 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3140 |             if (inProfile->mSupportedDevices.isEmpty()) { | 
 | 3141 |                 ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName); | 
 | 3142 |                 continue; | 
 | 3143 |             } | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3144 |             // chose first device present in mSupportedDevices also part of | 
 | 3145 |             // inputDeviceTypes | 
 | 3146 |             audio_devices_t profileType = AUDIO_DEVICE_NONE; | 
 | 3147 |             for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) { | 
 | 3148 |                 profileType = inProfile->mSupportedDevices[k]->mDeviceType; | 
 | 3149 |                 if (profileType & inputDeviceTypes) { | 
 | 3150 |                     break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3151 |                 } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3152 |             } | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3153 |             if ((profileType & inputDeviceTypes) == 0) { | 
 | 3154 |                 continue; | 
 | 3155 |             } | 
 | 3156 |             sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile); | 
 | 3157 |  | 
 | 3158 |             inputDesc->mInputSource = AUDIO_SOURCE_MIC; | 
 | 3159 |             inputDesc->mDevice = profileType; | 
 | 3160 |  | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 3161 |             // find the address | 
 | 3162 |             DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(profileType); | 
 | 3163 |             //   the inputs vector must be of size 1, but we don't want to crash here | 
 | 3164 |             String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress | 
 | 3165 |                     : String8(""); | 
 | 3166 |             ALOGV("  for input device 0x%x using address %s", profileType, address.string()); | 
 | 3167 |             ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!"); | 
 | 3168 |  | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3169 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 3170 |             config.sample_rate = inputDesc->mSamplingRate; | 
 | 3171 |             config.channel_mask = inputDesc->mChannelMask; | 
 | 3172 |             config.format = inputDesc->mFormat; | 
 | 3173 |             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; | 
 | 3174 |             status_t status = mpClientInterface->openInput(inProfile->mModule->mHandle, | 
 | 3175 |                                                            &input, | 
 | 3176 |                                                            &config, | 
 | 3177 |                                                            &inputDesc->mDevice, | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 3178 |                                                            address, | 
| Eric Laurent | d78f153 | 2014-09-16 16:38:20 -0700 | [diff] [blame] | 3179 |                                                            AUDIO_SOURCE_MIC, | 
 | 3180 |                                                            AUDIO_INPUT_FLAG_NONE); | 
 | 3181 |  | 
 | 3182 |             if (status == NO_ERROR) { | 
 | 3183 |                 for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) { | 
 | 3184 |                     audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType; | 
 | 3185 |                     ssize_t index = | 
 | 3186 |                             mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]); | 
 | 3187 |                     // give a valid ID to an attached device once confirmed it is reachable | 
 | 3188 |                     if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) { | 
 | 3189 |                         mAvailableInputDevices[index]->mId = nextUniqueId(); | 
 | 3190 |                         mAvailableInputDevices[index]->mModule = mHwModules[i]; | 
 | 3191 |                     } | 
 | 3192 |                 } | 
 | 3193 |                 mpClientInterface->closeInput(input); | 
 | 3194 |             } else { | 
 | 3195 |                 ALOGW("Cannot open input stream for device %08x on hw module %s", | 
 | 3196 |                       inputDesc->mDevice, | 
 | 3197 |                       mHwModules[i]->mName); | 
 | 3198 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3199 |         } | 
 | 3200 |     } | 
 | 3201 |     // make sure all attached devices have been allocated a unique ID | 
 | 3202 |     for (size_t i = 0; i  < mAvailableOutputDevices.size();) { | 
 | 3203 |         if (mAvailableOutputDevices[i]->mId == 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3204 |             ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3205 |             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]); | 
 | 3206 |             continue; | 
 | 3207 |         } | 
 | 3208 |         i++; | 
 | 3209 |     } | 
 | 3210 |     for (size_t i = 0; i  < mAvailableInputDevices.size();) { | 
 | 3211 |         if (mAvailableInputDevices[i]->mId == 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3212 |             ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3213 |             mAvailableInputDevices.remove(mAvailableInputDevices[i]); | 
 | 3214 |             continue; | 
 | 3215 |         } | 
 | 3216 |         i++; | 
 | 3217 |     } | 
 | 3218 |     // make sure default device is reachable | 
 | 3219 |     if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3220 |         ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3221 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3222 |  | 
 | 3223 |     ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); | 
 | 3224 |  | 
 | 3225 |     updateDevicesAndOutputs(); | 
 | 3226 |  | 
 | 3227 | #ifdef AUDIO_POLICY_TEST | 
 | 3228 |     if (mPrimaryOutput != 0) { | 
 | 3229 |         AudioParameter outputCmd = AudioParameter(); | 
 | 3230 |         outputCmd.addInt(String8("set_id"), 0); | 
 | 3231 |         mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); | 
 | 3232 |  | 
 | 3233 |         mTestDevice = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 3234 |         mTestSamplingRate = 44100; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3235 |         mTestFormat = AUDIO_FORMAT_PCM_16_BIT; | 
 | 3236 |         mTestChannels =  AUDIO_CHANNEL_OUT_STEREO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3237 |         mTestLatencyMs = 0; | 
 | 3238 |         mCurOutput = 0; | 
 | 3239 |         mDirectOutput = false; | 
 | 3240 |         for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { | 
 | 3241 |             mTestOutputs[i] = 0; | 
 | 3242 |         } | 
 | 3243 |  | 
 | 3244 |         const size_t SIZE = 256; | 
 | 3245 |         char buffer[SIZE]; | 
 | 3246 |         snprintf(buffer, SIZE, "AudioPolicyManagerTest"); | 
 | 3247 |         run(buffer, ANDROID_PRIORITY_AUDIO); | 
 | 3248 |     } | 
 | 3249 | #endif //AUDIO_POLICY_TEST | 
 | 3250 | } | 
 | 3251 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3252 | AudioPolicyManager::~AudioPolicyManager() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3253 | { | 
 | 3254 | #ifdef AUDIO_POLICY_TEST | 
 | 3255 |     exit(); | 
 | 3256 | #endif //AUDIO_POLICY_TEST | 
 | 3257 |    for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 3258 |         mpClientInterface->closeOutput(mOutputs.keyAt(i)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3259 |    } | 
 | 3260 |    for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 3261 |         mpClientInterface->closeInput(mInputs.keyAt(i)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3262 |    } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3263 |    mAvailableOutputDevices.clear(); | 
 | 3264 |    mAvailableInputDevices.clear(); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3265 |    mOutputs.clear(); | 
 | 3266 |    mInputs.clear(); | 
 | 3267 |    mHwModules.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3268 | } | 
 | 3269 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3270 | status_t AudioPolicyManager::initCheck() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3271 | { | 
 | 3272 |     return (mPrimaryOutput == 0) ? NO_INIT : NO_ERROR; | 
 | 3273 | } | 
 | 3274 |  | 
 | 3275 | #ifdef AUDIO_POLICY_TEST | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3276 | bool AudioPolicyManager::threadLoop() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3277 | { | 
 | 3278 |     ALOGV("entering threadLoop()"); | 
 | 3279 |     while (!exitPending()) | 
 | 3280 |     { | 
 | 3281 |         String8 command; | 
 | 3282 |         int valueInt; | 
 | 3283 |         String8 value; | 
 | 3284 |  | 
 | 3285 |         Mutex::Autolock _l(mLock); | 
 | 3286 |         mWaitWorkCV.waitRelative(mLock, milliseconds(50)); | 
 | 3287 |  | 
 | 3288 |         command = mpClientInterface->getParameters(0, String8("test_cmd_policy")); | 
 | 3289 |         AudioParameter param = AudioParameter(command); | 
 | 3290 |  | 
 | 3291 |         if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR && | 
 | 3292 |             valueInt != 0) { | 
 | 3293 |             ALOGV("Test command %s received", command.string()); | 
 | 3294 |             String8 target; | 
 | 3295 |             if (param.get(String8("target"), target) != NO_ERROR) { | 
 | 3296 |                 target = "Manager"; | 
 | 3297 |             } | 
 | 3298 |             if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) { | 
 | 3299 |                 param.remove(String8("test_cmd_policy_output")); | 
 | 3300 |                 mCurOutput = valueInt; | 
 | 3301 |             } | 
 | 3302 |             if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) { | 
 | 3303 |                 param.remove(String8("test_cmd_policy_direct")); | 
 | 3304 |                 if (value == "false") { | 
 | 3305 |                     mDirectOutput = false; | 
 | 3306 |                 } else if (value == "true") { | 
 | 3307 |                     mDirectOutput = true; | 
 | 3308 |                 } | 
 | 3309 |             } | 
 | 3310 |             if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) { | 
 | 3311 |                 param.remove(String8("test_cmd_policy_input")); | 
 | 3312 |                 mTestInput = valueInt; | 
 | 3313 |             } | 
 | 3314 |  | 
 | 3315 |             if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) { | 
 | 3316 |                 param.remove(String8("test_cmd_policy_format")); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3317 |                 int format = AUDIO_FORMAT_INVALID; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3318 |                 if (value == "PCM 16 bits") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3319 |                     format = AUDIO_FORMAT_PCM_16_BIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3320 |                 } else if (value == "PCM 8 bits") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3321 |                     format = AUDIO_FORMAT_PCM_8_BIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3322 |                 } else if (value == "Compressed MP3") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3323 |                     format = AUDIO_FORMAT_MP3; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3324 |                 } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3325 |                 if (format != AUDIO_FORMAT_INVALID) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3326 |                     if (target == "Manager") { | 
 | 3327 |                         mTestFormat = format; | 
 | 3328 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 3329 |                         AudioParameter outputParam = AudioParameter(); | 
 | 3330 |                         outputParam.addInt(String8("format"), format); | 
 | 3331 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 3332 |                     } | 
 | 3333 |                 } | 
 | 3334 |             } | 
 | 3335 |             if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) { | 
 | 3336 |                 param.remove(String8("test_cmd_policy_channels")); | 
 | 3337 |                 int channels = 0; | 
 | 3338 |  | 
 | 3339 |                 if (value == "Channels Stereo") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3340 |                     channels =  AUDIO_CHANNEL_OUT_STEREO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3341 |                 } else if (value == "Channels Mono") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3342 |                     channels =  AUDIO_CHANNEL_OUT_MONO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3343 |                 } | 
 | 3344 |                 if (channels != 0) { | 
 | 3345 |                     if (target == "Manager") { | 
 | 3346 |                         mTestChannels = channels; | 
 | 3347 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 3348 |                         AudioParameter outputParam = AudioParameter(); | 
 | 3349 |                         outputParam.addInt(String8("channels"), channels); | 
 | 3350 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 3351 |                     } | 
 | 3352 |                 } | 
 | 3353 |             } | 
 | 3354 |             if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) { | 
 | 3355 |                 param.remove(String8("test_cmd_policy_sampleRate")); | 
 | 3356 |                 if (valueInt >= 0 && valueInt <= 96000) { | 
 | 3357 |                     int samplingRate = valueInt; | 
 | 3358 |                     if (target == "Manager") { | 
 | 3359 |                         mTestSamplingRate = samplingRate; | 
 | 3360 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 3361 |                         AudioParameter outputParam = AudioParameter(); | 
 | 3362 |                         outputParam.addInt(String8("sampling_rate"), samplingRate); | 
 | 3363 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 3364 |                     } | 
 | 3365 |                 } | 
 | 3366 |             } | 
 | 3367 |  | 
 | 3368 |             if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) { | 
 | 3369 |                 param.remove(String8("test_cmd_policy_reopen")); | 
 | 3370 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3371 |                 sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3372 |                 mpClientInterface->closeOutput(mPrimaryOutput); | 
 | 3373 |  | 
 | 3374 |                 audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle; | 
 | 3375 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3376 |                 mOutputs.removeItem(mPrimaryOutput); | 
 | 3377 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3378 |                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3379 |                 outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3380 |                 audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 3381 |                 config.sample_rate = outputDesc->mSamplingRate; | 
 | 3382 |                 config.channel_mask = outputDesc->mChannelMask; | 
 | 3383 |                 config.format = outputDesc->mFormat; | 
 | 3384 |                 status_t status = mpClientInterface->openOutput(moduleHandle, | 
 | 3385 |                                                                 &mPrimaryOutput, | 
 | 3386 |                                                                 &config, | 
 | 3387 |                                                                 &outputDesc->mDevice, | 
 | 3388 |                                                                 String8(""), | 
 | 3389 |                                                                 &outputDesc->mLatency, | 
 | 3390 |                                                                 outputDesc->mFlags); | 
 | 3391 |                 if (status != NO_ERROR) { | 
 | 3392 |                     ALOGE("Failed to reopen hardware output stream, " | 
 | 3393 |                         "samplingRate: %d, format %d, channels %d", | 
 | 3394 |                         outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannelMask); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3395 |                 } else { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3396 |                     outputDesc->mSamplingRate = config.sample_rate; | 
 | 3397 |                     outputDesc->mChannelMask = config.channel_mask; | 
 | 3398 |                     outputDesc->mFormat = config.format; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3399 |                     AudioParameter outputCmd = AudioParameter(); | 
 | 3400 |                     outputCmd.addInt(String8("set_id"), 0); | 
 | 3401 |                     mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); | 
 | 3402 |                     addOutput(mPrimaryOutput, outputDesc); | 
 | 3403 |                 } | 
 | 3404 |             } | 
 | 3405 |  | 
 | 3406 |  | 
 | 3407 |             mpClientInterface->setParameters(0, String8("test_cmd_policy=")); | 
 | 3408 |         } | 
 | 3409 |     } | 
 | 3410 |     return false; | 
 | 3411 | } | 
 | 3412 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3413 | void AudioPolicyManager::exit() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3414 | { | 
 | 3415 |     { | 
 | 3416 |         AutoMutex _l(mLock); | 
 | 3417 |         requestExit(); | 
 | 3418 |         mWaitWorkCV.signal(); | 
 | 3419 |     } | 
 | 3420 |     requestExitAndWait(); | 
 | 3421 | } | 
 | 3422 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3423 | int AudioPolicyManager::testOutputIndex(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3424 | { | 
 | 3425 |     for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { | 
 | 3426 |         if (output == mTestOutputs[i]) return i; | 
 | 3427 |     } | 
 | 3428 |     return 0; | 
 | 3429 | } | 
 | 3430 | #endif //AUDIO_POLICY_TEST | 
 | 3431 |  | 
 | 3432 | // --- | 
 | 3433 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3434 | void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3435 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3436 |     outputDesc->mIoHandle = output; | 
 | 3437 |     outputDesc->mId = nextUniqueId(); | 
 | 3438 |     mOutputs.add(output, outputDesc); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3439 |     nextAudioPortGeneration(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3440 | } | 
 | 3441 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3442 | void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc) | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3443 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3444 |     inputDesc->mIoHandle = input; | 
 | 3445 |     inputDesc->mId = nextUniqueId(); | 
 | 3446 |     mInputs.add(input, inputDesc); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3447 |     nextAudioPortGeneration(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3448 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3449 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3450 | void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/, | 
| keunyoung | 3190e67 | 2014-12-30 13:00:52 -0800 | [diff] [blame] | 3451 |         const audio_devices_t device /*in*/, | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3452 |         const String8 address /*in*/, | 
 | 3453 |         SortedVector<audio_io_handle_t>& outputs /*out*/) { | 
| keunyoung | 3190e67 | 2014-12-30 13:00:52 -0800 | [diff] [blame] | 3454 |     sp<DeviceDescriptor> devDesc = | 
 | 3455 |         desc->mProfile->mSupportedDevices.getDevice(device, address); | 
 | 3456 |     if (devDesc != 0) { | 
 | 3457 |         ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s", | 
 | 3458 |               desc->mIoHandle, address.string()); | 
 | 3459 |         outputs.add(desc->mIoHandle); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3460 |     } | 
 | 3461 | } | 
 | 3462 |  | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 3463 | status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> devDesc, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3464 |                                                        audio_policy_dev_state_t state, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3465 |                                                        SortedVector<audio_io_handle_t>& outputs, | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3466 |                                                        const String8 address) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3467 | { | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 3468 |     audio_devices_t device = devDesc->mDeviceType; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3469 |     sp<AudioOutputDescriptor> desc; | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 3470 |     // erase all current sample rates, formats and channel masks | 
 | 3471 |     devDesc->clearCapabilities(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3472 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3473 |     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3474 |         // first list already open outputs that can be routed to this device | 
 | 3475 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 3476 |             desc = mOutputs.valueAt(i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3477 |             if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3478 |                 if (!deviceDistinguishesOnAddress(device)) { | 
 | 3479 |                     ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i)); | 
 | 3480 |                     outputs.add(mOutputs.keyAt(i)); | 
 | 3481 |                 } else { | 
 | 3482 |                     ALOGV("  checking address match due to device 0x%x", device); | 
| keunyoung | 3190e67 | 2014-12-30 13:00:52 -0800 | [diff] [blame] | 3483 |                     findIoHandlesByAddress(desc, device, address, outputs); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3484 |                 } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3485 |             } | 
 | 3486 |         } | 
 | 3487 |         // then look for output profiles that can be routed to this device | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3488 |         SortedVector< sp<IOProfile> > profiles; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3489 |         for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 3490 |         { | 
 | 3491 |             if (mHwModules[i]->mHandle == 0) { | 
 | 3492 |                 continue; | 
 | 3493 |             } | 
 | 3494 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 3495 |             { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3496 |                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
 | 3497 |                 if (profile->mSupportedDevices.types() & device) { | 
 | 3498 |                     if (!deviceDistinguishesOnAddress(device) || | 
 | 3499 |                             address == profile->mSupportedDevices[0]->mAddress) { | 
 | 3500 |                         profiles.add(profile); | 
 | 3501 |                         ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i); | 
 | 3502 |                     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3503 |                 } | 
 | 3504 |             } | 
 | 3505 |         } | 
 | 3506 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3507 |         ALOGV("  found %d profiles, %d outputs", profiles.size(), outputs.size()); | 
 | 3508 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3509 |         if (profiles.isEmpty() && outputs.isEmpty()) { | 
 | 3510 |             ALOGW("checkOutputsForDevice(): No output available for device %04x", device); | 
 | 3511 |             return BAD_VALUE; | 
 | 3512 |         } | 
 | 3513 |  | 
 | 3514 |         // open outputs for matching profiles if needed. Direct outputs are also opened to | 
 | 3515 |         // query for dynamic parameters and will be closed later by setDeviceConnectionState() | 
 | 3516 |         for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3517 |             sp<IOProfile> profile = profiles[profile_index]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3518 |  | 
 | 3519 |             // nothing to do if one output is already opened for this profile | 
 | 3520 |             size_t j; | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3521 |             for (j = 0; j < outputs.size(); j++) { | 
 | 3522 |                 desc = mOutputs.valueFor(outputs.itemAt(j)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3523 |                 if (!desc->isDuplicated() && desc->mProfile == profile) { | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 3524 |                     // matching profile: save the sample rates, format and channel masks supported | 
 | 3525 |                     // by the profile in our device descriptor | 
 | 3526 |                     devDesc->importAudioPort(profile); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3527 |                     break; | 
 | 3528 |                 } | 
 | 3529 |             } | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3530 |             if (j != outputs.size()) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3531 |                 continue; | 
 | 3532 |             } | 
 | 3533 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 3534 |             ALOGV("opening output for device %08x with params %s profile %p", | 
 | 3535 |                                                       device, address.string(), profile.get()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3536 |             desc = new AudioOutputDescriptor(profile); | 
 | 3537 |             desc->mDevice = device; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3538 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 3539 |             config.sample_rate = desc->mSamplingRate; | 
 | 3540 |             config.channel_mask = desc->mChannelMask; | 
 | 3541 |             config.format = desc->mFormat; | 
 | 3542 |             config.offload_info.sample_rate = desc->mSamplingRate; | 
 | 3543 |             config.offload_info.channel_mask = desc->mChannelMask; | 
 | 3544 |             config.offload_info.format = desc->mFormat; | 
 | 3545 |             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; | 
 | 3546 |             status_t status = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 3547 |                                                             &output, | 
 | 3548 |                                                             &config, | 
 | 3549 |                                                             &desc->mDevice, | 
 | 3550 |                                                             address, | 
 | 3551 |                                                             &desc->mLatency, | 
 | 3552 |                                                             desc->mFlags); | 
 | 3553 |             if (status == NO_ERROR) { | 
 | 3554 |                 desc->mSamplingRate = config.sample_rate; | 
 | 3555 |                 desc->mChannelMask = config.channel_mask; | 
 | 3556 |                 desc->mFormat = config.format; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3557 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3558 |                 // Here is where the out_set_parameters() for card & device gets called | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3559 |                 if (!address.isEmpty()) { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3560 |                     char *param = audio_device_address_to_parameter(device, address); | 
 | 3561 |                     mpClientInterface->setParameters(output, String8(param)); | 
 | 3562 |                     free(param); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3563 |                 } | 
 | 3564 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3565 |                 // Here is where we step through and resolve any "dynamic" fields | 
 | 3566 |                 String8 reply; | 
 | 3567 |                 char *value; | 
 | 3568 |                 if (profile->mSamplingRates[0] == 0) { | 
 | 3569 |                     reply = mpClientInterface->getParameters(output, | 
 | 3570 |                                             String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3571 |                     ALOGV("checkOutputsForDevice() supported sampling rates %s", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3572 |                               reply.string()); | 
 | 3573 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3574 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3575 |                         profile->loadSamplingRates(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3576 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3577 |                 } | 
 | 3578 |                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3579 |                     reply = mpClientInterface->getParameters(output, | 
 | 3580 |                                                    String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3581 |                     ALOGV("checkOutputsForDevice() supported formats %s", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3582 |                               reply.string()); | 
 | 3583 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3584 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3585 |                         profile->loadFormats(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3586 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3587 |                 } | 
 | 3588 |                 if (profile->mChannelMasks[0] == 0) { | 
 | 3589 |                     reply = mpClientInterface->getParameters(output, | 
 | 3590 |                                                   String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3591 |                     ALOGV("checkOutputsForDevice() supported channel masks %s", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3592 |                               reply.string()); | 
 | 3593 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3594 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3595 |                         profile->loadOutChannels(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3596 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3597 |                 } | 
 | 3598 |                 if (((profile->mSamplingRates[0] == 0) && | 
 | 3599 |                          (profile->mSamplingRates.size() < 2)) || | 
 | 3600 |                      ((profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) && | 
 | 3601 |                          (profile->mFormats.size() < 2)) || | 
 | 3602 |                      ((profile->mChannelMasks[0] == 0) && | 
 | 3603 |                          (profile->mChannelMasks.size() < 2))) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3604 |                     ALOGW("checkOutputsForDevice() missing param"); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3605 |                     mpClientInterface->closeOutput(output); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3606 |                     output = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 3607 |                 } else if (profile->mSamplingRates[0] == 0 || profile->mFormats[0] == 0 || | 
 | 3608 |                             profile->mChannelMasks[0] == 0) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3609 |                     mpClientInterface->closeOutput(output); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3610 |                     config.sample_rate = profile->pickSamplingRate(); | 
 | 3611 |                     config.channel_mask = profile->pickChannelMask(); | 
 | 3612 |                     config.format = profile->pickFormat(); | 
 | 3613 |                     config.offload_info.sample_rate = config.sample_rate; | 
 | 3614 |                     config.offload_info.channel_mask = config.channel_mask; | 
 | 3615 |                     config.offload_info.format = config.format; | 
 | 3616 |                     status = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 3617 |                                                            &output, | 
 | 3618 |                                                            &config, | 
 | 3619 |                                                            &desc->mDevice, | 
 | 3620 |                                                            address, | 
 | 3621 |                                                            &desc->mLatency, | 
 | 3622 |                                                            desc->mFlags); | 
 | 3623 |                     if (status == NO_ERROR) { | 
 | 3624 |                         desc->mSamplingRate = config.sample_rate; | 
 | 3625 |                         desc->mChannelMask = config.channel_mask; | 
 | 3626 |                         desc->mFormat = config.format; | 
 | 3627 |                     } else { | 
 | 3628 |                         output = AUDIO_IO_HANDLE_NONE; | 
 | 3629 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3630 |                 } | 
 | 3631 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3632 |                 if (output != AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3633 |                     addOutput(output, desc); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3634 |                     if (deviceDistinguishesOnAddress(device) && address != "0") { | 
 | 3635 |                         ssize_t index = mPolicyMixes.indexOfKey(address); | 
 | 3636 |                         if (index >= 0) { | 
 | 3637 |                             mPolicyMixes[index]->mOutput = desc; | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 3638 |                             desc->mPolicyMix = &mPolicyMixes[index]->mMix; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3639 |                         } else { | 
 | 3640 |                             ALOGE("checkOutputsForDevice() cannot find policy for address %s", | 
 | 3641 |                                   address.string()); | 
 | 3642 |                         } | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 3643 |                     } else if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) { | 
 | 3644 |                         // no duplicated output for direct outputs and | 
 | 3645 |                         // outputs used by dynamic policy mixes | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3646 |                         audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3647 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3648 |                         // set initial stream volume for device | 
 | 3649 |                         applyStreamVolumes(output, device, 0, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3650 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3651 |                         //TODO: configure audio effect output stage here | 
 | 3652 |  | 
 | 3653 |                         // open a duplicating output thread for the new output and the primary output | 
 | 3654 |                         duplicatedOutput = mpClientInterface->openDuplicateOutput(output, | 
 | 3655 |                                                                                   mPrimaryOutput); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3656 |                         if (duplicatedOutput != AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3657 |                             // add duplicated output descriptor | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3658 |                             sp<AudioOutputDescriptor> dupOutputDesc = | 
 | 3659 |                                     new AudioOutputDescriptor(NULL); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3660 |                             dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput); | 
 | 3661 |                             dupOutputDesc->mOutput2 = mOutputs.valueFor(output); | 
 | 3662 |                             dupOutputDesc->mSamplingRate = desc->mSamplingRate; | 
 | 3663 |                             dupOutputDesc->mFormat = desc->mFormat; | 
 | 3664 |                             dupOutputDesc->mChannelMask = desc->mChannelMask; | 
 | 3665 |                             dupOutputDesc->mLatency = desc->mLatency; | 
 | 3666 |                             addOutput(duplicatedOutput, dupOutputDesc); | 
 | 3667 |                             applyStreamVolumes(duplicatedOutput, device, 0, true); | 
 | 3668 |                         } else { | 
 | 3669 |                             ALOGW("checkOutputsForDevice() could not open dup output for %d and %d", | 
 | 3670 |                                     mPrimaryOutput, output); | 
 | 3671 |                             mpClientInterface->closeOutput(output); | 
 | 3672 |                             mOutputs.removeItem(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3673 |                             nextAudioPortGeneration(); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3674 |                             output = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3675 |                         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3676 |                     } | 
 | 3677 |                 } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3678 |             } else { | 
 | 3679 |                 output = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3680 |             } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3681 |             if (output == AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3682 |                 ALOGW("checkOutputsForDevice() could not open output for device %x", device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3683 |                 profiles.removeAt(profile_index); | 
 | 3684 |                 profile_index--; | 
 | 3685 |             } else { | 
 | 3686 |                 outputs.add(output); | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 3687 |                 devDesc->importAudioPort(profile); | 
 | 3688 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3689 |                 if (deviceDistinguishesOnAddress(device)) { | 
 | 3690 |                     ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)", | 
 | 3691 |                             device, address.string()); | 
 | 3692 |                     setOutputDevice(output, device, true/*force*/, 0/*delay*/, | 
 | 3693 |                             NULL/*patch handle*/, address.string()); | 
 | 3694 |                 } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3695 |                 ALOGV("checkOutputsForDevice(): adding output %d", output); | 
 | 3696 |             } | 
 | 3697 |         } | 
 | 3698 |  | 
 | 3699 |         if (profiles.isEmpty()) { | 
 | 3700 |             ALOGW("checkOutputsForDevice(): No output available for device %04x", device); | 
 | 3701 |             return BAD_VALUE; | 
 | 3702 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3703 |     } else { // Disconnect | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3704 |         // check if one opened output is not needed any more after disconnecting one device | 
 | 3705 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 3706 |             desc = mOutputs.valueAt(i); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3707 |             if (!desc->isDuplicated()) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3708 |                 // exact match on device | 
 | 3709 |                 if (deviceDistinguishesOnAddress(device) && | 
 | 3710 |                         (desc->mProfile->mSupportedDevices.types() == device)) { | 
| keunyoung | 3190e67 | 2014-12-30 13:00:52 -0800 | [diff] [blame] | 3711 |                     findIoHandlesByAddress(desc, device, address, outputs); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3712 |                 } else if (!(desc->mProfile->mSupportedDevices.types() | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3713 |                         & mAvailableOutputDevices.types())) { | 
 | 3714 |                     ALOGV("checkOutputsForDevice(): disconnecting adding output %d", | 
 | 3715 |                             mOutputs.keyAt(i)); | 
 | 3716 |                     outputs.add(mOutputs.keyAt(i)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3717 |                 } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3718 |             } | 
 | 3719 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3720 |         // Clear any profiles associated with the disconnected device. | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3721 |         for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 3722 |         { | 
 | 3723 |             if (mHwModules[i]->mHandle == 0) { | 
 | 3724 |                 continue; | 
 | 3725 |             } | 
 | 3726 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 3727 |             { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3728 |                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3729 |                 if (profile->mSupportedDevices.types() & device) { | 
 | 3730 |                     ALOGV("checkOutputsForDevice(): " | 
 | 3731 |                             "clearing direct output profile %zu on module %zu", j, i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3732 |                     if (profile->mSamplingRates[0] == 0) { | 
 | 3733 |                         profile->mSamplingRates.clear(); | 
 | 3734 |                         profile->mSamplingRates.add(0); | 
 | 3735 |                     } | 
 | 3736 |                     if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3737 |                         profile->mFormats.clear(); | 
 | 3738 |                         profile->mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 3739 |                     } | 
 | 3740 |                     if (profile->mChannelMasks[0] == 0) { | 
 | 3741 |                         profile->mChannelMasks.clear(); | 
 | 3742 |                         profile->mChannelMasks.add(0); | 
 | 3743 |                     } | 
 | 3744 |                 } | 
 | 3745 |             } | 
 | 3746 |         } | 
 | 3747 |     } | 
 | 3748 |     return NO_ERROR; | 
 | 3749 | } | 
 | 3750 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3751 | status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device, | 
 | 3752 |                                                       audio_policy_dev_state_t state, | 
 | 3753 |                                                       SortedVector<audio_io_handle_t>& inputs, | 
 | 3754 |                                                       const String8 address) | 
 | 3755 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3756 |     sp<AudioInputDescriptor> desc; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3757 |     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { | 
 | 3758 |         // first list already open inputs that can be routed to this device | 
 | 3759 |         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3760 |             desc = mInputs.valueAt(input_index); | 
 | 3761 |             if (desc->mProfile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) { | 
 | 3762 |                 ALOGV("checkInputsForDevice(): adding opened input %d", mInputs.keyAt(input_index)); | 
 | 3763 |                inputs.add(mInputs.keyAt(input_index)); | 
 | 3764 |             } | 
 | 3765 |         } | 
 | 3766 |  | 
 | 3767 |         // then look for input profiles that can be routed to this device | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3768 |         SortedVector< sp<IOProfile> > profiles; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3769 |         for (size_t module_idx = 0; module_idx < mHwModules.size(); module_idx++) | 
 | 3770 |         { | 
 | 3771 |             if (mHwModules[module_idx]->mHandle == 0) { | 
 | 3772 |                 continue; | 
 | 3773 |             } | 
 | 3774 |             for (size_t profile_index = 0; | 
 | 3775 |                  profile_index < mHwModules[module_idx]->mInputProfiles.size(); | 
 | 3776 |                  profile_index++) | 
 | 3777 |             { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3778 |                 sp<IOProfile> profile = mHwModules[module_idx]->mInputProfiles[profile_index]; | 
 | 3779 |  | 
 | 3780 |                 if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) { | 
 | 3781 |                     if (!deviceDistinguishesOnAddress(device) || | 
 | 3782 |                             address == profile->mSupportedDevices[0]->mAddress) { | 
 | 3783 |                         profiles.add(profile); | 
 | 3784 |                         ALOGV("checkInputsForDevice(): adding profile %zu from module %zu", | 
 | 3785 |                               profile_index, module_idx); | 
 | 3786 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3787 |                 } | 
 | 3788 |             } | 
 | 3789 |         } | 
 | 3790 |  | 
 | 3791 |         if (profiles.isEmpty() && inputs.isEmpty()) { | 
 | 3792 |             ALOGW("checkInputsForDevice(): No input available for device 0x%X", device); | 
 | 3793 |             return BAD_VALUE; | 
 | 3794 |         } | 
 | 3795 |  | 
 | 3796 |         // open inputs for matching profiles if needed. Direct inputs are also opened to | 
 | 3797 |         // query for dynamic parameters and will be closed later by setDeviceConnectionState() | 
 | 3798 |         for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) { | 
 | 3799 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3800 |             sp<IOProfile> profile = profiles[profile_index]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3801 |             // nothing to do if one input is already opened for this profile | 
 | 3802 |             size_t input_index; | 
 | 3803 |             for (input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3804 |                 desc = mInputs.valueAt(input_index); | 
 | 3805 |                 if (desc->mProfile == profile) { | 
 | 3806 |                     break; | 
 | 3807 |                 } | 
 | 3808 |             } | 
 | 3809 |             if (input_index != mInputs.size()) { | 
 | 3810 |                 continue; | 
 | 3811 |             } | 
 | 3812 |  | 
 | 3813 |             ALOGV("opening input for device 0x%X with params %s", device, address.string()); | 
 | 3814 |             desc = new AudioInputDescriptor(profile); | 
 | 3815 |             desc->mDevice = device; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3816 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 3817 |             config.sample_rate = desc->mSamplingRate; | 
 | 3818 |             config.channel_mask = desc->mChannelMask; | 
 | 3819 |             config.format = desc->mFormat; | 
 | 3820 |             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; | 
 | 3821 |             status_t status = mpClientInterface->openInput(profile->mModule->mHandle, | 
 | 3822 |                                                            &input, | 
 | 3823 |                                                            &config, | 
 | 3824 |                                                            &desc->mDevice, | 
 | 3825 |                                                            address, | 
 | 3826 |                                                            AUDIO_SOURCE_MIC, | 
 | 3827 |                                                            AUDIO_INPUT_FLAG_NONE /*FIXME*/); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3828 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3829 |             if (status == NO_ERROR) { | 
 | 3830 |                 desc->mSamplingRate = config.sample_rate; | 
 | 3831 |                 desc->mChannelMask = config.channel_mask; | 
 | 3832 |                 desc->mFormat = config.format; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3833 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3834 |                 if (!address.isEmpty()) { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3835 |                     char *param = audio_device_address_to_parameter(device, address); | 
 | 3836 |                     mpClientInterface->setParameters(input, String8(param)); | 
 | 3837 |                     free(param); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3838 |                 } | 
 | 3839 |  | 
 | 3840 |                 // Here is where we step through and resolve any "dynamic" fields | 
 | 3841 |                 String8 reply; | 
 | 3842 |                 char *value; | 
 | 3843 |                 if (profile->mSamplingRates[0] == 0) { | 
 | 3844 |                     reply = mpClientInterface->getParameters(input, | 
 | 3845 |                                             String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); | 
 | 3846 |                     ALOGV("checkInputsForDevice() direct input sup sampling rates %s", | 
 | 3847 |                               reply.string()); | 
 | 3848 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3849 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3850 |                         profile->loadSamplingRates(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3851 |                     } | 
 | 3852 |                 } | 
 | 3853 |                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3854 |                     reply = mpClientInterface->getParameters(input, | 
 | 3855 |                                                    String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); | 
 | 3856 |                     ALOGV("checkInputsForDevice() direct input sup formats %s", reply.string()); | 
 | 3857 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3858 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3859 |                         profile->loadFormats(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3860 |                     } | 
 | 3861 |                 } | 
 | 3862 |                 if (profile->mChannelMasks[0] == 0) { | 
 | 3863 |                     reply = mpClientInterface->getParameters(input, | 
 | 3864 |                                                   String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); | 
 | 3865 |                     ALOGV("checkInputsForDevice() direct input sup channel masks %s", | 
 | 3866 |                               reply.string()); | 
 | 3867 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3868 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3869 |                         profile->loadInChannels(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3870 |                     } | 
 | 3871 |                 } | 
 | 3872 |                 if (((profile->mSamplingRates[0] == 0) && (profile->mSamplingRates.size() < 2)) || | 
 | 3873 |                      ((profile->mFormats[0] == 0) && (profile->mFormats.size() < 2)) || | 
 | 3874 |                      ((profile->mChannelMasks[0] == 0) && (profile->mChannelMasks.size() < 2))) { | 
 | 3875 |                     ALOGW("checkInputsForDevice() direct input missing param"); | 
 | 3876 |                     mpClientInterface->closeInput(input); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3877 |                     input = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3878 |                 } | 
 | 3879 |  | 
 | 3880 |                 if (input != 0) { | 
 | 3881 |                     addInput(input, desc); | 
 | 3882 |                 } | 
 | 3883 |             } // endif input != 0 | 
 | 3884 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3885 |             if (input == AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3886 |                 ALOGW("checkInputsForDevice() could not open input for device 0x%X", device); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3887 |                 profiles.removeAt(profile_index); | 
 | 3888 |                 profile_index--; | 
 | 3889 |             } else { | 
 | 3890 |                 inputs.add(input); | 
 | 3891 |                 ALOGV("checkInputsForDevice(): adding input %d", input); | 
 | 3892 |             } | 
 | 3893 |         } // end scan profiles | 
 | 3894 |  | 
 | 3895 |         if (profiles.isEmpty()) { | 
 | 3896 |             ALOGW("checkInputsForDevice(): No input available for device 0x%X", device); | 
 | 3897 |             return BAD_VALUE; | 
 | 3898 |         } | 
 | 3899 |     } else { | 
 | 3900 |         // Disconnect | 
 | 3901 |         // check if one opened input is not needed any more after disconnecting one device | 
 | 3902 |         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3903 |             desc = mInputs.valueAt(input_index); | 
| Eric Laurent | ddbc665 | 2014-11-13 15:13:44 -0800 | [diff] [blame] | 3904 |             if (!(desc->mProfile->mSupportedDevices.types() & mAvailableInputDevices.types() & | 
 | 3905 |                     ~AUDIO_DEVICE_BIT_IN)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3906 |                 ALOGV("checkInputsForDevice(): disconnecting adding input %d", | 
 | 3907 |                       mInputs.keyAt(input_index)); | 
 | 3908 |                 inputs.add(mInputs.keyAt(input_index)); | 
 | 3909 |             } | 
 | 3910 |         } | 
 | 3911 |         // Clear any profiles associated with the disconnected device. | 
 | 3912 |         for (size_t module_index = 0; module_index < mHwModules.size(); module_index++) { | 
 | 3913 |             if (mHwModules[module_index]->mHandle == 0) { | 
 | 3914 |                 continue; | 
 | 3915 |             } | 
 | 3916 |             for (size_t profile_index = 0; | 
 | 3917 |                  profile_index < mHwModules[module_index]->mInputProfiles.size(); | 
 | 3918 |                  profile_index++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3919 |                 sp<IOProfile> profile = mHwModules[module_index]->mInputProfiles[profile_index]; | 
| Eric Laurent | ddbc665 | 2014-11-13 15:13:44 -0800 | [diff] [blame] | 3920 |                 if (profile->mSupportedDevices.types() & device & ~AUDIO_DEVICE_BIT_IN) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 3921 |                     ALOGV("checkInputsForDevice(): clearing direct input profile %zu on module %zu", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3922 |                           profile_index, module_index); | 
 | 3923 |                     if (profile->mSamplingRates[0] == 0) { | 
 | 3924 |                         profile->mSamplingRates.clear(); | 
 | 3925 |                         profile->mSamplingRates.add(0); | 
 | 3926 |                     } | 
 | 3927 |                     if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3928 |                         profile->mFormats.clear(); | 
 | 3929 |                         profile->mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 3930 |                     } | 
 | 3931 |                     if (profile->mChannelMasks[0] == 0) { | 
 | 3932 |                         profile->mChannelMasks.clear(); | 
 | 3933 |                         profile->mChannelMasks.add(0); | 
 | 3934 |                     } | 
 | 3935 |                 } | 
 | 3936 |             } | 
 | 3937 |         } | 
 | 3938 |     } // end disconnect | 
 | 3939 |  | 
 | 3940 |     return NO_ERROR; | 
 | 3941 | } | 
 | 3942 |  | 
 | 3943 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3944 | void AudioPolicyManager::closeOutput(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3945 | { | 
 | 3946 |     ALOGV("closeOutput(%d)", output); | 
 | 3947 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3948 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3949 |     if (outputDesc == NULL) { | 
 | 3950 |         ALOGW("closeOutput() unknown output %d", output); | 
 | 3951 |         return; | 
 | 3952 |     } | 
 | 3953 |  | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 3954 |     for (size_t i = 0; i < mPolicyMixes.size(); i++) { | 
 | 3955 |         if (mPolicyMixes[i]->mOutput == outputDesc) { | 
 | 3956 |             mPolicyMixes[i]->mOutput.clear(); | 
 | 3957 |         } | 
 | 3958 |     } | 
 | 3959 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3960 |     // look for duplicated outputs connected to the output being removed. | 
 | 3961 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3962 |         sp<AudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3963 |         if (dupOutputDesc->isDuplicated() && | 
 | 3964 |                 (dupOutputDesc->mOutput1 == outputDesc || | 
 | 3965 |                 dupOutputDesc->mOutput2 == outputDesc)) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3966 |             sp<AudioOutputDescriptor> outputDesc2; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3967 |             if (dupOutputDesc->mOutput1 == outputDesc) { | 
 | 3968 |                 outputDesc2 = dupOutputDesc->mOutput2; | 
 | 3969 |             } else { | 
 | 3970 |                 outputDesc2 = dupOutputDesc->mOutput1; | 
 | 3971 |             } | 
 | 3972 |             // As all active tracks on duplicated output will be deleted, | 
 | 3973 |             // and as they were also referenced on the other output, the reference | 
 | 3974 |             // count for their stream type must be adjusted accordingly on | 
 | 3975 |             // the other output. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3976 |             for (int j = 0; j < AUDIO_STREAM_CNT; j++) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3977 |                 int refCount = dupOutputDesc->mRefCount[j]; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3978 |                 outputDesc2->changeRefCount((audio_stream_type_t)j,-refCount); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3979 |             } | 
 | 3980 |             audio_io_handle_t duplicatedOutput = mOutputs.keyAt(i); | 
 | 3981 |             ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput); | 
 | 3982 |  | 
 | 3983 |             mpClientInterface->closeOutput(duplicatedOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3984 |             mOutputs.removeItem(duplicatedOutput); | 
 | 3985 |         } | 
 | 3986 |     } | 
 | 3987 |  | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 3988 |     nextAudioPortGeneration(); | 
 | 3989 |  | 
 | 3990 |     ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3991 |     if (index >= 0) { | 
 | 3992 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3993 |         status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
 | 3994 |         mAudioPatches.removeItemsAt(index); | 
 | 3995 |         mpClientInterface->onAudioPatchListUpdate(); | 
 | 3996 |     } | 
 | 3997 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3998 |     AudioParameter param; | 
 | 3999 |     param.add(String8("closing"), String8("true")); | 
 | 4000 |     mpClientInterface->setParameters(output, param.toString()); | 
 | 4001 |  | 
 | 4002 |     mpClientInterface->closeOutput(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4003 |     mOutputs.removeItem(output); | 
 | 4004 |     mPreviousOutputs = mOutputs; | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 4005 | } | 
 | 4006 |  | 
 | 4007 | void AudioPolicyManager::closeInput(audio_io_handle_t input) | 
 | 4008 | { | 
 | 4009 |     ALOGV("closeInput(%d)", input); | 
 | 4010 |  | 
 | 4011 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
 | 4012 |     if (inputDesc == NULL) { | 
 | 4013 |         ALOGW("closeInput() unknown input %d", input); | 
 | 4014 |         return; | 
 | 4015 |     } | 
 | 4016 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4017 |     nextAudioPortGeneration(); | 
| Eric Laurent | 05b90f8 | 2014-08-27 15:32:29 -0700 | [diff] [blame] | 4018 |  | 
 | 4019 |     ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 4020 |     if (index >= 0) { | 
 | 4021 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 4022 |         status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
 | 4023 |         mAudioPatches.removeItemsAt(index); | 
 | 4024 |         mpClientInterface->onAudioPatchListUpdate(); | 
 | 4025 |     } | 
 | 4026 |  | 
 | 4027 |     mpClientInterface->closeInput(input); | 
 | 4028 |     mInputs.removeItem(input); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4029 | } | 
 | 4030 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4031 | SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device, | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4032 |                         DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4033 | { | 
 | 4034 |     SortedVector<audio_io_handle_t> outputs; | 
 | 4035 |  | 
 | 4036 |     ALOGVV("getOutputsForDevice() device %04x", device); | 
 | 4037 |     for (size_t i = 0; i < openOutputs.size(); i++) { | 
 | 4038 |         ALOGVV("output %d isDuplicated=%d device=%04x", | 
 | 4039 |                 i, openOutputs.valueAt(i)->isDuplicated(), openOutputs.valueAt(i)->supportedDevices()); | 
 | 4040 |         if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) { | 
 | 4041 |             ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i)); | 
 | 4042 |             outputs.add(openOutputs.keyAt(i)); | 
 | 4043 |         } | 
 | 4044 |     } | 
 | 4045 |     return outputs; | 
 | 4046 | } | 
 | 4047 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4048 | bool AudioPolicyManager::vectorsEqual(SortedVector<audio_io_handle_t>& outputs1, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4049 |                                    SortedVector<audio_io_handle_t>& outputs2) | 
 | 4050 | { | 
 | 4051 |     if (outputs1.size() != outputs2.size()) { | 
 | 4052 |         return false; | 
 | 4053 |     } | 
 | 4054 |     for (size_t i = 0; i < outputs1.size(); i++) { | 
 | 4055 |         if (outputs1[i] != outputs2[i]) { | 
 | 4056 |             return false; | 
 | 4057 |         } | 
 | 4058 |     } | 
 | 4059 |     return true; | 
 | 4060 | } | 
 | 4061 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4062 | void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4063 | { | 
 | 4064 |     audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/); | 
 | 4065 |     audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 4066 |     SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs); | 
 | 4067 |     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs); | 
 | 4068 |  | 
| Jean-Michel Trivi | fe472e2 | 2014-12-16 14:23:13 -0800 | [diff] [blame] | 4069 |     // also take into account external policy-related changes: add all outputs which are | 
 | 4070 |     // associated with policies in the "before" and "after" output vectors | 
 | 4071 |     ALOGVV("checkOutputForStrategy(): policy related outputs"); | 
 | 4072 |     for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) { | 
 | 4073 |         const sp<AudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i); | 
 | 4074 |         if (desc != 0 && desc->mPolicyMix != NULL) { | 
 | 4075 |             srcOutputs.add(desc->mIoHandle); | 
 | 4076 |             ALOGVV(" previous outputs: adding %d", desc->mIoHandle); | 
 | 4077 |         } | 
 | 4078 |     } | 
 | 4079 |     for (size_t i = 0 ; i < mOutputs.size() ; i++) { | 
 | 4080 |         const sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
 | 4081 |         if (desc != 0 && desc->mPolicyMix != NULL) { | 
 | 4082 |             dstOutputs.add(desc->mIoHandle); | 
 | 4083 |             ALOGVV(" new outputs: adding %d", desc->mIoHandle); | 
 | 4084 |         } | 
 | 4085 |     } | 
 | 4086 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4087 |     if (!vectorsEqual(srcOutputs,dstOutputs)) { | 
 | 4088 |         ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d", | 
 | 4089 |               strategy, srcOutputs[0], dstOutputs[0]); | 
 | 4090 |         // mute strategy while moving tracks from one output to another | 
 | 4091 |         for (size_t i = 0; i < srcOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4092 |             sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4093 |             if (desc->isStrategyActive(strategy)) { | 
 | 4094 |                 setStrategyMute(strategy, true, srcOutputs[i]); | 
 | 4095 |                 setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); | 
 | 4096 |             } | 
 | 4097 |         } | 
 | 4098 |  | 
 | 4099 |         // Move effects associated to this strategy from previous output to new output | 
 | 4100 |         if (strategy == STRATEGY_MEDIA) { | 
 | 4101 |             audio_io_handle_t fxOutput = selectOutputForEffects(dstOutputs); | 
 | 4102 |             SortedVector<audio_io_handle_t> moved; | 
 | 4103 |             for (size_t i = 0; i < mEffects.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4104 |                 sp<EffectDescriptor> effectDesc = mEffects.valueAt(i); | 
 | 4105 |                 if (effectDesc->mSession == AUDIO_SESSION_OUTPUT_MIX && | 
 | 4106 |                         effectDesc->mIo != fxOutput) { | 
 | 4107 |                     if (moved.indexOf(effectDesc->mIo) < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4108 |                         ALOGV("checkOutputForStrategy() moving effect %d to output %d", | 
 | 4109 |                               mEffects.keyAt(i), fxOutput); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4110 |                         mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, effectDesc->mIo, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4111 |                                                        fxOutput); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4112 |                         moved.add(effectDesc->mIo); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4113 |                     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4114 |                     effectDesc->mIo = fxOutput; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4115 |                 } | 
 | 4116 |             } | 
 | 4117 |         } | 
 | 4118 |         // Move tracks associated to this strategy from previous output to new output | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4119 |         for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4120 |             if (i == AUDIO_STREAM_PATCH) { | 
 | 4121 |                 continue; | 
 | 4122 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4123 |             if (getStrategy((audio_stream_type_t)i) == strategy) { | 
 | 4124 |                 mpClientInterface->invalidateStream((audio_stream_type_t)i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4125 |             } | 
 | 4126 |         } | 
 | 4127 |     } | 
 | 4128 | } | 
 | 4129 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4130 | void AudioPolicyManager::checkOutputForAllStrategies() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4131 | { | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4132 |     if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) | 
 | 4133 |         checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4134 |     checkOutputForStrategy(STRATEGY_PHONE); | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4135 |     if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) | 
 | 4136 |         checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4137 |     checkOutputForStrategy(STRATEGY_SONIFICATION); | 
 | 4138 |     checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4139 |     checkOutputForStrategy(STRATEGY_ACCESSIBILITY); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4140 |     checkOutputForStrategy(STRATEGY_MEDIA); | 
 | 4141 |     checkOutputForStrategy(STRATEGY_DTMF); | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4142 |     checkOutputForStrategy(STRATEGY_REROUTING); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4143 | } | 
 | 4144 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4145 | audio_io_handle_t AudioPolicyManager::getA2dpOutput() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4146 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4147 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4148 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4149 |         if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { | 
 | 4150 |             return mOutputs.keyAt(i); | 
 | 4151 |         } | 
 | 4152 |     } | 
 | 4153 |  | 
 | 4154 |     return 0; | 
 | 4155 | } | 
 | 4156 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4157 | void AudioPolicyManager::checkA2dpSuspend() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4158 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4159 |     audio_io_handle_t a2dpOutput = getA2dpOutput(); | 
 | 4160 |     if (a2dpOutput == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4161 |         mA2dpSuspended = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4162 |         return; | 
 | 4163 |     } | 
 | 4164 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4165 |     bool isScoConnected = | 
| Eric Laurent | ddbc665 | 2014-11-13 15:13:44 -0800 | [diff] [blame] | 4166 |             ((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET & | 
 | 4167 |                     ~AUDIO_DEVICE_BIT_IN) != 0) || | 
 | 4168 |             ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_ALL_SCO) != 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4169 |     // suspend A2DP output if: | 
 | 4170 |     //      (NOT already suspended) && | 
 | 4171 |     //      ((SCO device is connected && | 
 | 4172 |     //       (forced usage for communication || for record is SCO))) || | 
 | 4173 |     //      (phone state is ringing || in call) | 
 | 4174 |     // | 
 | 4175 |     // restore A2DP output if: | 
 | 4176 |     //      (Already suspended) && | 
 | 4177 |     //      ((SCO device is NOT connected || | 
 | 4178 |     //       (forced usage NOT for communication && NOT for record is SCO))) && | 
 | 4179 |     //      (phone state is NOT ringing && NOT in call) | 
 | 4180 |     // | 
 | 4181 |     if (mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4182 |         if ((!isScoConnected || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4183 |              ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO) && | 
 | 4184 |               (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] != AUDIO_POLICY_FORCE_BT_SCO))) && | 
 | 4185 |              ((mPhoneState != AUDIO_MODE_IN_CALL) && | 
 | 4186 |               (mPhoneState != AUDIO_MODE_RINGTONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4187 |  | 
 | 4188 |             mpClientInterface->restoreOutput(a2dpOutput); | 
 | 4189 |             mA2dpSuspended = false; | 
 | 4190 |         } | 
 | 4191 |     } else { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4192 |         if ((isScoConnected && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4193 |              ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) || | 
 | 4194 |               (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO))) || | 
 | 4195 |              ((mPhoneState == AUDIO_MODE_IN_CALL) || | 
 | 4196 |               (mPhoneState == AUDIO_MODE_RINGTONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4197 |  | 
 | 4198 |             mpClientInterface->suspendOutput(a2dpOutput); | 
 | 4199 |             mA2dpSuspended = true; | 
 | 4200 |         } | 
 | 4201 |     } | 
 | 4202 | } | 
 | 4203 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4204 | audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, bool fromCache) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4205 | { | 
 | 4206 |     audio_devices_t device = AUDIO_DEVICE_NONE; | 
 | 4207 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4208 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4209 |  | 
 | 4210 |     ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 4211 |     if (index >= 0) { | 
 | 4212 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 4213 |         if (patchDesc->mUid != mUidCached) { | 
 | 4214 |             ALOGV("getNewOutputDevice() device %08x forced by patch %d", | 
 | 4215 |                   outputDesc->device(), outputDesc->mPatchHandle); | 
 | 4216 |             return outputDesc->device(); | 
 | 4217 |         } | 
 | 4218 |     } | 
 | 4219 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4220 |     // check the following by order of priority to request a routing change if necessary: | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4221 |     // 1: the strategy enforced audible is active and enforced on the output: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4222 |     //      use device for strategy enforced audible | 
 | 4223 |     // 2: we are in call or the strategy phone is active on the output: | 
 | 4224 |     //      use device for strategy phone | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4225 |     // 3: the strategy for enforced audible is active but not enforced on the output: | 
 | 4226 |     //      use the device for strategy enforced audible | 
 | 4227 |     // 4: the strategy sonification is active on the output: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4228 |     //      use device for strategy sonification | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4229 |     // 5: the strategy "respectful" sonification is active on the output: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4230 |     //      use device for strategy "respectful" sonification | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4231 |     // 6: the strategy accessibility is active on the output: | 
 | 4232 |     //      use device for strategy accessibility | 
 | 4233 |     // 7: the strategy media is active on the output: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4234 |     //      use device for strategy media | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4235 |     // 8: the strategy DTMF is active on the output: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4236 |     //      use device for strategy DTMF | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4237 |     // 9: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output: | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 4238 |     //      use device for strategy t-t-s | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4239 |     if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE) && | 
 | 4240 |         mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4241 |         device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache); | 
 | 4242 |     } else if (isInCall() || | 
 | 4243 |                     outputDesc->isStrategyActive(STRATEGY_PHONE)) { | 
 | 4244 |         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache); | 
| Jon Eklund | 966095e | 2014-09-09 15:39:49 -0500 | [diff] [blame] | 4245 |     } else if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) { | 
 | 4246 |         device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4247 |     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) { | 
 | 4248 |         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache); | 
 | 4249 |     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) { | 
 | 4250 |         device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache); | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4251 |     } else if (outputDesc->isStrategyActive(STRATEGY_ACCESSIBILITY)) { | 
 | 4252 |         device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4253 |     } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) { | 
 | 4254 |         device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache); | 
 | 4255 |     } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) { | 
 | 4256 |         device = getDeviceForStrategy(STRATEGY_DTMF, fromCache); | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 4257 |     } else if (outputDesc->isStrategyActive(STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) { | 
 | 4258 |         device = getDeviceForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache); | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4259 |     } else if (outputDesc->isStrategyActive(STRATEGY_REROUTING)) { | 
 | 4260 |         device = getDeviceForStrategy(STRATEGY_REROUTING, fromCache); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4261 |     } | 
 | 4262 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4263 |     ALOGV("getNewOutputDevice() selected device %x", device); | 
 | 4264 |     return device; | 
 | 4265 | } | 
 | 4266 |  | 
 | 4267 | audio_devices_t AudioPolicyManager::getNewInputDevice(audio_io_handle_t input) | 
 | 4268 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4269 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4270 |  | 
 | 4271 |     ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 4272 |     if (index >= 0) { | 
 | 4273 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 4274 |         if (patchDesc->mUid != mUidCached) { | 
 | 4275 |             ALOGV("getNewInputDevice() device %08x forced by patch %d", | 
 | 4276 |                   inputDesc->mDevice, inputDesc->mPatchHandle); | 
 | 4277 |             return inputDesc->mDevice; | 
 | 4278 |         } | 
 | 4279 |     } | 
 | 4280 |  | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 4281 |     audio_devices_t device = getDeviceAndMixForInputSource(inputDesc->mInputSource); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4282 |  | 
 | 4283 |     ALOGV("getNewInputDevice() selected device %x", device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4284 |     return device; | 
 | 4285 | } | 
 | 4286 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4287 | uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4288 |     return (uint32_t)getStrategy(stream); | 
 | 4289 | } | 
 | 4290 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4291 | audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4292 |     // By checking the range of stream before calling getStrategy, we avoid | 
 | 4293 |     // getStrategy's behavior for invalid streams.  getStrategy would do a ALOGE | 
 | 4294 |     // and then return STRATEGY_MEDIA, but we want to return the empty set. | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4295 |     if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4296 |         return AUDIO_DEVICE_NONE; | 
 | 4297 |     } | 
 | 4298 |     audio_devices_t devices; | 
 | 4299 |     AudioPolicyManager::routing_strategy strategy = getStrategy(stream); | 
 | 4300 |     devices = getDeviceForStrategy(strategy, true /*fromCache*/); | 
 | 4301 |     SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs); | 
 | 4302 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4303 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4304 |         if (outputDesc->isStrategyActive(strategy)) { | 
 | 4305 |             devices = outputDesc->device(); | 
 | 4306 |             break; | 
 | 4307 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4308 |     } | 
| Jon Eklund | 11c9fb1 | 2014-06-23 14:47:03 -0500 | [diff] [blame] | 4309 |  | 
 | 4310 |     /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it | 
 | 4311 |       and doesn't really need to.*/ | 
 | 4312 |     if (devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) { | 
 | 4313 |         devices |= AUDIO_DEVICE_OUT_SPEAKER; | 
 | 4314 |         devices &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE; | 
 | 4315 |     } | 
 | 4316 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4317 |     return devices; | 
 | 4318 | } | 
 | 4319 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4320 | AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4321 |         audio_stream_type_t stream) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4322 |  | 
 | 4323 |     ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH"); | 
 | 4324 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4325 |     // stream to strategy mapping | 
 | 4326 |     switch (stream) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4327 |     case AUDIO_STREAM_VOICE_CALL: | 
 | 4328 |     case AUDIO_STREAM_BLUETOOTH_SCO: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4329 |         return STRATEGY_PHONE; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4330 |     case AUDIO_STREAM_RING: | 
 | 4331 |     case AUDIO_STREAM_ALARM: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4332 |         return STRATEGY_SONIFICATION; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4333 |     case AUDIO_STREAM_NOTIFICATION: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4334 |         return STRATEGY_SONIFICATION_RESPECTFUL; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4335 |     case AUDIO_STREAM_DTMF: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4336 |         return STRATEGY_DTMF; | 
 | 4337 |     default: | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4338 |         ALOGE("unknown stream type %d", stream); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4339 |     case AUDIO_STREAM_SYSTEM: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4340 |         // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs | 
 | 4341 |         // while key clicks are played produces a poor result | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4342 |     case AUDIO_STREAM_MUSIC: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4343 |         return STRATEGY_MEDIA; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4344 |     case AUDIO_STREAM_ENFORCED_AUDIBLE: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4345 |         return STRATEGY_ENFORCED_AUDIBLE; | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 4346 |     case AUDIO_STREAM_TTS: | 
 | 4347 |         return STRATEGY_TRANSMITTED_THROUGH_SPEAKER; | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4348 |     case AUDIO_STREAM_ACCESSIBILITY: | 
 | 4349 |         return STRATEGY_ACCESSIBILITY; | 
 | 4350 |     case AUDIO_STREAM_REROUTING: | 
 | 4351 |         return STRATEGY_REROUTING; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4352 |     } | 
 | 4353 | } | 
 | 4354 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 4355 | uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) { | 
 | 4356 |     // flags to strategy mapping | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 4357 |     if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) { | 
 | 4358 |         return (uint32_t) STRATEGY_TRANSMITTED_THROUGH_SPEAKER; | 
 | 4359 |     } | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 4360 |     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { | 
 | 4361 |         return (uint32_t) STRATEGY_ENFORCED_AUDIBLE; | 
 | 4362 |     } | 
 | 4363 |  | 
 | 4364 |     // usage to strategy mapping | 
 | 4365 |     switch (attr->usage) { | 
| Eric Laurent | 29e6cec | 2014-11-13 18:17:55 -0800 | [diff] [blame] | 4366 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
 | 4367 |         if (isStreamActive(AUDIO_STREAM_RING) || isStreamActive(AUDIO_STREAM_ALARM)) { | 
 | 4368 |             return (uint32_t) STRATEGY_SONIFICATION; | 
 | 4369 |         } | 
 | 4370 |         if (isInCall()) { | 
 | 4371 |             return (uint32_t) STRATEGY_PHONE; | 
 | 4372 |         } | 
| Eric Laurent | 0f78eab | 2014-11-25 11:01:34 -0800 | [diff] [blame] | 4373 |         return (uint32_t) STRATEGY_ACCESSIBILITY; | 
| Eric Laurent | 29e6cec | 2014-11-13 18:17:55 -0800 | [diff] [blame] | 4374 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 4375 |     case AUDIO_USAGE_MEDIA: | 
 | 4376 |     case AUDIO_USAGE_GAME: | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 4377 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 4378 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 4379 |         return (uint32_t) STRATEGY_MEDIA; | 
 | 4380 |  | 
 | 4381 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 4382 |         return (uint32_t) STRATEGY_PHONE; | 
 | 4383 |  | 
 | 4384 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 4385 |         return (uint32_t) STRATEGY_DTMF; | 
 | 4386 |  | 
 | 4387 |     case AUDIO_USAGE_ALARM: | 
 | 4388 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 4389 |         return (uint32_t) STRATEGY_SONIFICATION; | 
 | 4390 |  | 
 | 4391 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 4392 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 4393 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 4394 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 4395 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 4396 |         return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL; | 
 | 4397 |  | 
 | 4398 |     case AUDIO_USAGE_UNKNOWN: | 
 | 4399 |     default: | 
 | 4400 |         return (uint32_t) STRATEGY_MEDIA; | 
 | 4401 |     } | 
 | 4402 | } | 
 | 4403 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4404 | void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4405 |     switch(stream) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4406 |     case AUDIO_STREAM_MUSIC: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4407 |         checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 4408 |         updateDevicesAndOutputs(); | 
 | 4409 |         break; | 
 | 4410 |     default: | 
 | 4411 |         break; | 
 | 4412 |     } | 
 | 4413 | } | 
 | 4414 |  | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 4415 | bool AudioPolicyManager::isAnyOutputActive(audio_stream_type_t streamToIgnore) { | 
 | 4416 |     for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) { | 
 | 4417 |         if (s == (size_t) streamToIgnore) { | 
 | 4418 |             continue; | 
 | 4419 |         } | 
 | 4420 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 4421 |             const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
 | 4422 |             if (outputDesc->mRefCount[s] != 0) { | 
 | 4423 |                 return true; | 
 | 4424 |             } | 
 | 4425 |         } | 
 | 4426 |     } | 
 | 4427 |     return false; | 
 | 4428 | } | 
 | 4429 |  | 
 | 4430 | uint32_t AudioPolicyManager::handleEventForBeacon(int event) { | 
 | 4431 |     switch(event) { | 
 | 4432 |     case STARTING_OUTPUT: | 
 | 4433 |         mBeaconMuteRefCount++; | 
 | 4434 |         break; | 
 | 4435 |     case STOPPING_OUTPUT: | 
 | 4436 |         if (mBeaconMuteRefCount > 0) { | 
 | 4437 |             mBeaconMuteRefCount--; | 
 | 4438 |         } | 
 | 4439 |         break; | 
 | 4440 |     case STARTING_BEACON: | 
 | 4441 |         mBeaconPlayingRefCount++; | 
 | 4442 |         break; | 
 | 4443 |     case STOPPING_BEACON: | 
 | 4444 |         if (mBeaconPlayingRefCount > 0) { | 
 | 4445 |             mBeaconPlayingRefCount--; | 
 | 4446 |         } | 
 | 4447 |         break; | 
 | 4448 |     } | 
 | 4449 |  | 
 | 4450 |     if (mBeaconMuteRefCount > 0) { | 
 | 4451 |         // any playback causes beacon to be muted | 
 | 4452 |         return setBeaconMute(true); | 
 | 4453 |     } else { | 
 | 4454 |         // no other playback: unmute when beacon starts playing, mute when it stops | 
 | 4455 |         return setBeaconMute(mBeaconPlayingRefCount == 0); | 
 | 4456 |     } | 
 | 4457 | } | 
 | 4458 |  | 
 | 4459 | uint32_t AudioPolicyManager::setBeaconMute(bool mute) { | 
 | 4460 |     ALOGV("setBeaconMute(%d) mBeaconMuteRefCount=%d mBeaconPlayingRefCount=%d", | 
 | 4461 |             mute, mBeaconMuteRefCount, mBeaconPlayingRefCount); | 
 | 4462 |     // keep track of muted state to avoid repeating mute/unmute operations | 
 | 4463 |     if (mBeaconMuted != mute) { | 
 | 4464 |         // mute/unmute AUDIO_STREAM_TTS on all outputs | 
 | 4465 |         ALOGV("\t muting %d", mute); | 
 | 4466 |         uint32_t maxLatency = 0; | 
 | 4467 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 4468 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
 | 4469 |             setStreamMute(AUDIO_STREAM_TTS, mute/*on*/, | 
 | 4470 |                     desc->mIoHandle, | 
 | 4471 |                     0 /*delay*/, AUDIO_DEVICE_NONE); | 
 | 4472 |             const uint32_t latency = desc->latency() * 2; | 
 | 4473 |             if (latency > maxLatency) { | 
 | 4474 |                 maxLatency = latency; | 
 | 4475 |             } | 
 | 4476 |         } | 
 | 4477 |         mBeaconMuted = mute; | 
 | 4478 |         return maxLatency; | 
 | 4479 |     } | 
 | 4480 |     return 0; | 
 | 4481 | } | 
 | 4482 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4483 | audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4484 |                                                              bool fromCache) | 
 | 4485 | { | 
 | 4486 |     uint32_t device = AUDIO_DEVICE_NONE; | 
 | 4487 |  | 
 | 4488 |     if (fromCache) { | 
 | 4489 |         ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x", | 
 | 4490 |               strategy, mDeviceForStrategy[strategy]); | 
 | 4491 |         return mDeviceForStrategy[strategy]; | 
 | 4492 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4493 |     audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4494 |     switch (strategy) { | 
 | 4495 |  | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 4496 |     case STRATEGY_TRANSMITTED_THROUGH_SPEAKER: | 
 | 4497 |         device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
 | 4498 |         if (!device) { | 
 | 4499 |             ALOGE("getDeviceForStrategy() no device found for "\ | 
 | 4500 |                     "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"); | 
 | 4501 |         } | 
 | 4502 |         break; | 
 | 4503 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4504 |     case STRATEGY_SONIFICATION_RESPECTFUL: | 
 | 4505 |         if (isInCall()) { | 
 | 4506 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4507 |         } else if (isStreamActiveRemotely(AUDIO_STREAM_MUSIC, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4508 |                 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { | 
 | 4509 |             // while media is playing on a remote device, use the the sonification behavior. | 
 | 4510 |             // Note that we test this usecase before testing if media is playing because | 
 | 4511 |             //   the isStreamActive() method only informs about the activity of a stream, not | 
 | 4512 |             //   if it's for local playback. Note also that we use the same delay between both tests | 
 | 4513 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Jon Eklund | 11c9fb1 | 2014-06-23 14:47:03 -0500 | [diff] [blame] | 4514 |             //user "safe" speaker if available instead of normal speaker to avoid triggering | 
 | 4515 |             //other acoustic safety mechanisms for notification | 
 | 4516 |             if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) | 
 | 4517 |                 device = AUDIO_DEVICE_OUT_SPEAKER_SAFE; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4518 |         } else if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4519 |             // while media is playing (or has recently played), use the same device | 
 | 4520 |             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); | 
 | 4521 |         } else { | 
 | 4522 |             // when media is not playing anymore, fall back on the sonification behavior | 
 | 4523 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Jon Eklund | 11c9fb1 | 2014-06-23 14:47:03 -0500 | [diff] [blame] | 4524 |             //user "safe" speaker if available instead of normal speaker to avoid triggering | 
 | 4525 |             //other acoustic safety mechanisms for notification | 
 | 4526 |             if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) | 
 | 4527 |                 device = AUDIO_DEVICE_OUT_SPEAKER_SAFE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4528 |         } | 
 | 4529 |  | 
 | 4530 |         break; | 
 | 4531 |  | 
 | 4532 |     case STRATEGY_DTMF: | 
 | 4533 |         if (!isInCall()) { | 
 | 4534 |             // when off call, DTMF strategy follows the same rules as MEDIA strategy | 
 | 4535 |             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); | 
 | 4536 |             break; | 
 | 4537 |         } | 
 | 4538 |         // when in call, DTMF and PHONE strategies follow the same rules | 
 | 4539 |         // FALL THROUGH | 
 | 4540 |  | 
 | 4541 |     case STRATEGY_PHONE: | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 4542 |         // Force use of only devices on primary output if: | 
 | 4543 |         // - in call AND | 
 | 4544 |         //   - cannot route from voice call RX OR | 
 | 4545 |         //   - audio HAL version is < 3.0 and TX device is on the primary HW module | 
 | 4546 |         if (mPhoneState == AUDIO_MODE_IN_CALL) { | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 4547 |             audio_devices_t txDevice = | 
 | 4548 |                     getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION); | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 4549 |             sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); | 
 | 4550 |             if (((mAvailableInputDevices.types() & | 
 | 4551 |                     AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) || | 
 | 4552 |                     (((txDevice & availablePrimaryInputDevices() & ~AUDIO_DEVICE_BIT_IN) != 0) && | 
| Marco Nelissen | 961ec21 | 2014-08-25 15:58:39 -0700 | [diff] [blame] | 4553 |                          (hwOutputDesc->getAudioPort()->mModule->mHalVersion < | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 4554 |                              AUDIO_DEVICE_API_VERSION_3_0))) { | 
 | 4555 |                 availableOutputDeviceTypes = availablePrimaryOutputDevices(); | 
 | 4556 |             } | 
 | 4557 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4558 |         // for phone strategy, we first consider the forced use and then the available devices by order | 
 | 4559 |         // of priority | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4560 |         switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) { | 
 | 4561 |         case AUDIO_POLICY_FORCE_BT_SCO: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4562 |             if (!isInCall() || strategy != STRATEGY_DTMF) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4563 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4564 |                 if (device) break; | 
 | 4565 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4566 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4567 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4568 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4569 |             if (device) break; | 
 | 4570 |             // if SCO device is requested but no SCO device is available, fall back to default case | 
 | 4571 |             // FALL THROUGH | 
 | 4572 |  | 
 | 4573 |         default:    // FORCE_NONE | 
 | 4574 |             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4575 |             if (!isInCall() && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4576 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | 29e6cec | 2014-11-13 18:17:55 -0800 | [diff] [blame] | 4577 |                     (getA2dpOutput() != 0)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4578 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4579 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4580 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4581 |                 if (device) break; | 
 | 4582 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4583 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4584 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4585 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4586 |             if (device) break; | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 4587 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
 | 4588 |             if (device) break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4589 |             if (mPhoneState != AUDIO_MODE_IN_CALL) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4590 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4591 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4592 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4593 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4594 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4595 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4596 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4597 |                 if (device) break; | 
 | 4598 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4599 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4600 |             if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4601 |             device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4602 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 4603 |                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE"); | 
 | 4604 |             } | 
 | 4605 |             break; | 
 | 4606 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4607 |         case AUDIO_POLICY_FORCE_SPEAKER: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4608 |             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to | 
 | 4609 |             // A2DP speaker when forcing to speaker output | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4610 |             if (!isInCall() && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4611 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | 29e6cec | 2014-11-13 18:17:55 -0800 | [diff] [blame] | 4612 |                     (getA2dpOutput() != 0)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4613 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4614 |                 if (device) break; | 
 | 4615 |             } | 
| Eric Laurent | cd71a69 | 2014-12-16 12:01:12 -0800 | [diff] [blame] | 4616 |             if (!isInCall()) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4617 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4618 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4619 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4620 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4621 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4622 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4623 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4624 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4625 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4626 |                 if (device) break; | 
 | 4627 |             } | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 4628 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_LINE; | 
 | 4629 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4630 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4631 |             if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4632 |             device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4633 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 4634 |                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER"); | 
 | 4635 |             } | 
 | 4636 |             break; | 
 | 4637 |         } | 
 | 4638 |     break; | 
 | 4639 |  | 
 | 4640 |     case STRATEGY_SONIFICATION: | 
 | 4641 |  | 
 | 4642 |         // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by | 
 | 4643 |         // handleIncallSonification(). | 
 | 4644 |         if (isInCall()) { | 
 | 4645 |             device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/); | 
 | 4646 |             break; | 
 | 4647 |         } | 
 | 4648 |         // FALL THROUGH | 
 | 4649 |  | 
 | 4650 |     case STRATEGY_ENFORCED_AUDIBLE: | 
 | 4651 |         // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION | 
 | 4652 |         // except: | 
 | 4653 |         //   - when in call where it doesn't default to STRATEGY_PHONE behavior | 
 | 4654 |         //   - in countries where not enforced in which case it follows STRATEGY_MEDIA | 
 | 4655 |  | 
 | 4656 |         if ((strategy == STRATEGY_SONIFICATION) || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4657 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4658 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4659 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 4660 |                 ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION"); | 
 | 4661 |             } | 
 | 4662 |         } | 
 | 4663 |         // The second device used for sonification is the same as the device used by media strategy | 
 | 4664 |         // FALL THROUGH | 
 | 4665 |  | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4666 |     // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now | 
 | 4667 |     case STRATEGY_ACCESSIBILITY: | 
| Eric Laurent | 066ceec | 2014-11-25 12:35:01 -0800 | [diff] [blame] | 4668 |         if (strategy == STRATEGY_ACCESSIBILITY) { | 
 | 4669 |             // do not route accessibility prompts to a digital output currently configured with a | 
 | 4670 |             // compressed format as they would likely not be mixed and dropped. | 
 | 4671 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 4672 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
 | 4673 |                 audio_devices_t devices = desc->device() & | 
 | 4674 |                     (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC); | 
 | 4675 |                 if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) && | 
 | 4676 |                         devices != AUDIO_DEVICE_NONE) { | 
 | 4677 |                     availableOutputDeviceTypes = availableOutputDeviceTypes & ~devices; | 
 | 4678 |                 } | 
 | 4679 |             } | 
 | 4680 |         } | 
 | 4681 |         // FALL THROUGH | 
 | 4682 |  | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 4683 |     case STRATEGY_REROUTING: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4684 |     case STRATEGY_MEDIA: { | 
 | 4685 |         uint32_t device2 = AUDIO_DEVICE_NONE; | 
 | 4686 |         if (strategy != STRATEGY_SONIFICATION) { | 
 | 4687 |             // no sonification on remote submix (e.g. WFD) | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 4688 |             if (mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) { | 
 | 4689 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; | 
 | 4690 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4691 |         } | 
 | 4692 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4693 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | 29e6cec | 2014-11-13 18:17:55 -0800 | [diff] [blame] | 4694 |                 (getA2dpOutput() != 0)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4695 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4696 |             if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4697 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4698 |             } | 
 | 4699 |             if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4700 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4701 |             } | 
 | 4702 |         } | 
| Hochi Huang | 327cb70 | 2014-09-21 09:47:31 +0800 | [diff] [blame] | 4703 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
 | 4704 |             (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) { | 
 | 4705 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
 | 4706 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4707 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4708 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4709 |         } | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 4710 |         if ((device2 == AUDIO_DEVICE_NONE)) { | 
 | 4711 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_LINE; | 
 | 4712 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4713 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4714 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4715 |         } | 
 | 4716 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4717 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4718 |         } | 
 | 4719 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4720 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4721 |         } | 
 | 4722 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4723 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4724 |         } | 
 | 4725 |         if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { | 
 | 4726 |             // no sonification on aux digital (e.g. HDMI) | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4727 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4728 |         } | 
 | 4729 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4730 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4731 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4732 |         } | 
 | 4733 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4734 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4735 |         } | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 4736 |         int device3 = AUDIO_DEVICE_NONE; | 
 | 4737 |         if (strategy == STRATEGY_MEDIA) { | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 4738 |             // ARC, SPDIF and AUX_LINE can co-exist with others. | 
| Jungshik Jang | 0c94309 | 2014-07-08 22:11:24 +0900 | [diff] [blame] | 4739 |             device3 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_HDMI_ARC; | 
 | 4740 |             device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPDIF); | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 4741 |             device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_LINE); | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 4742 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4743 |  | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 4744 |         device2 |= device3; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4745 |         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or | 
 | 4746 |         // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise | 
 | 4747 |         device |= device2; | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 4748 |  | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 4749 |         // If hdmi system audio mode is on, remove speaker out of output list. | 
 | 4750 |         if ((strategy == STRATEGY_MEDIA) && | 
 | 4751 |             (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] == | 
 | 4752 |                 AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { | 
 | 4753 |             device &= ~AUDIO_DEVICE_OUT_SPEAKER; | 
 | 4754 |         } | 
 | 4755 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4756 |         if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4757 |         device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4758 |         if (device == AUDIO_DEVICE_NONE) { | 
 | 4759 |             ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA"); | 
 | 4760 |         } | 
 | 4761 |         } break; | 
 | 4762 |  | 
 | 4763 |     default: | 
 | 4764 |         ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); | 
 | 4765 |         break; | 
 | 4766 |     } | 
 | 4767 |  | 
 | 4768 |     ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); | 
 | 4769 |     return device; | 
 | 4770 | } | 
 | 4771 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4772 | void AudioPolicyManager::updateDevicesAndOutputs() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4773 | { | 
 | 4774 |     for (int i = 0; i < NUM_STRATEGIES; i++) { | 
 | 4775 |         mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); | 
 | 4776 |     } | 
 | 4777 |     mPreviousOutputs = mOutputs; | 
 | 4778 | } | 
 | 4779 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4780 | uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> outputDesc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4781 |                                                        audio_devices_t prevDevice, | 
 | 4782 |                                                        uint32_t delayMs) | 
 | 4783 | { | 
 | 4784 |     // mute/unmute strategies using an incompatible device combination | 
 | 4785 |     // if muting, wait for the audio in pcm buffer to be drained before proceeding | 
 | 4786 |     // if unmuting, unmute only after the specified delay | 
 | 4787 |     if (outputDesc->isDuplicated()) { | 
 | 4788 |         return 0; | 
 | 4789 |     } | 
 | 4790 |  | 
 | 4791 |     uint32_t muteWaitMs = 0; | 
 | 4792 |     audio_devices_t device = outputDesc->device(); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4793 |     bool shouldMute = outputDesc->isActive() && (popcount(device) >= 2); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4794 |  | 
 | 4795 |     for (size_t i = 0; i < NUM_STRATEGIES; i++) { | 
 | 4796 |         audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); | 
| Eric Laurent | 31551f8 | 2014-10-10 18:21:56 -0700 | [diff] [blame] | 4797 |         curDevice = curDevice & outputDesc->mProfile->mSupportedDevices.types(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4798 |         bool mute = shouldMute && (curDevice & device) && (curDevice != device); | 
 | 4799 |         bool doMute = false; | 
 | 4800 |  | 
 | 4801 |         if (mute && !outputDesc->mStrategyMutedByDevice[i]) { | 
 | 4802 |             doMute = true; | 
 | 4803 |             outputDesc->mStrategyMutedByDevice[i] = true; | 
 | 4804 |         } else if (!mute && outputDesc->mStrategyMutedByDevice[i]){ | 
 | 4805 |             doMute = true; | 
 | 4806 |             outputDesc->mStrategyMutedByDevice[i] = false; | 
 | 4807 |         } | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 4808 |         if (doMute) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4809 |             for (size_t j = 0; j < mOutputs.size(); j++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4810 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(j); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4811 |                 // skip output if it does not share any device with current output | 
 | 4812 |                 if ((desc->supportedDevices() & outputDesc->supportedDevices()) | 
 | 4813 |                         == AUDIO_DEVICE_NONE) { | 
 | 4814 |                     continue; | 
 | 4815 |                 } | 
 | 4816 |                 audio_io_handle_t curOutput = mOutputs.keyAt(j); | 
 | 4817 |                 ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d", | 
 | 4818 |                       mute ? "muting" : "unmuting", i, curDevice, curOutput); | 
 | 4819 |                 setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs); | 
 | 4820 |                 if (desc->isStrategyActive((routing_strategy)i)) { | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 4821 |                     if (mute) { | 
 | 4822 |                         // FIXME: should not need to double latency if volume could be applied | 
 | 4823 |                         // immediately by the audioflinger mixer. We must account for the delay | 
 | 4824 |                         // between now and the next time the audioflinger thread for this output | 
 | 4825 |                         // will process a buffer (which corresponds to one buffer size, | 
 | 4826 |                         // usually 1/2 or 1/4 of the latency). | 
 | 4827 |                         if (muteWaitMs < desc->latency() * 2) { | 
 | 4828 |                             muteWaitMs = desc->latency() * 2; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4829 |                         } | 
 | 4830 |                     } | 
 | 4831 |                 } | 
 | 4832 |             } | 
 | 4833 |         } | 
 | 4834 |     } | 
 | 4835 |  | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 4836 |     // temporary mute output if device selection changes to avoid volume bursts due to | 
 | 4837 |     // different per device volumes | 
 | 4838 |     if (outputDesc->isActive() && (device != prevDevice)) { | 
 | 4839 |         if (muteWaitMs < outputDesc->latency() * 2) { | 
 | 4840 |             muteWaitMs = outputDesc->latency() * 2; | 
 | 4841 |         } | 
 | 4842 |         for (size_t i = 0; i < NUM_STRATEGIES; i++) { | 
 | 4843 |             if (outputDesc->isStrategyActive((routing_strategy)i)) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4844 |                 setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle); | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 4845 |                 // do tempMute unmute after twice the mute wait time | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4846 |                 setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle, | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 4847 |                                 muteWaitMs *2, device); | 
 | 4848 |             } | 
 | 4849 |         } | 
 | 4850 |     } | 
 | 4851 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4852 |     // wait for the PCM output buffers to empty before proceeding with the rest of the command | 
 | 4853 |     if (muteWaitMs > delayMs) { | 
 | 4854 |         muteWaitMs -= delayMs; | 
 | 4855 |         usleep(muteWaitMs * 1000); | 
 | 4856 |         return muteWaitMs; | 
 | 4857 |     } | 
 | 4858 |     return 0; | 
 | 4859 | } | 
 | 4860 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4861 | uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4862 |                                              audio_devices_t device, | 
 | 4863 |                                              bool force, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4864 |                                              int delayMs, | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 4865 |                                              audio_patch_handle_t *patchHandle, | 
 | 4866 |                                              const char* address) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4867 | { | 
 | 4868 |     ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4869 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4870 |     AudioParameter param; | 
 | 4871 |     uint32_t muteWaitMs; | 
 | 4872 |  | 
 | 4873 |     if (outputDesc->isDuplicated()) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4874 |         muteWaitMs = setOutputDevice(outputDesc->mOutput1->mIoHandle, device, force, delayMs); | 
 | 4875 |         muteWaitMs += setOutputDevice(outputDesc->mOutput2->mIoHandle, device, force, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4876 |         return muteWaitMs; | 
 | 4877 |     } | 
 | 4878 |     // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current | 
 | 4879 |     // output profile | 
 | 4880 |     if ((device != AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4881 |             ((device & outputDesc->mProfile->mSupportedDevices.types()) == 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4882 |         return 0; | 
 | 4883 |     } | 
 | 4884 |  | 
 | 4885 |     // filter devices according to output selected | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4886 |     device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4887 |  | 
 | 4888 |     audio_devices_t prevDevice = outputDesc->mDevice; | 
 | 4889 |  | 
 | 4890 |     ALOGV("setOutputDevice() prevDevice %04x", prevDevice); | 
 | 4891 |  | 
 | 4892 |     if (device != AUDIO_DEVICE_NONE) { | 
 | 4893 |         outputDesc->mDevice = device; | 
 | 4894 |     } | 
 | 4895 |     muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs); | 
 | 4896 |  | 
 | 4897 |     // Do not change the routing if: | 
| Eric Laurent | b80a2a8 | 2014-10-27 16:07:59 -0700 | [diff] [blame] | 4898 |     //      the requested device is AUDIO_DEVICE_NONE | 
 | 4899 |     //      OR the requested device is the same as current device | 
 | 4900 |     //  AND force is not specified | 
 | 4901 |     //  AND the output is connected by a valid audio patch. | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4902 |     // Doing this check here allows the caller to call setOutputDevice() without conditions | 
| Eric Laurent | b80a2a8 | 2014-10-27 16:07:59 -0700 | [diff] [blame] | 4903 |     if ((device == AUDIO_DEVICE_NONE || device == prevDevice) && !force && | 
 | 4904 |             outputDesc->mPatchHandle != 0) { | 
 | 4905 |         ALOGV("setOutputDevice() setting same device %04x or null device for output %d", | 
 | 4906 |               device, output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4907 |         return muteWaitMs; | 
 | 4908 |     } | 
 | 4909 |  | 
 | 4910 |     ALOGV("setOutputDevice() changing device"); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4911 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4912 |     // do the routing | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4913 |     if (device == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4914 |         resetOutputDevice(output, delayMs, NULL); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4915 |     } else { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 4916 |         DeviceVector deviceList = (address == NULL) ? | 
 | 4917 |                 mAvailableOutputDevices.getDevicesFromType(device) | 
 | 4918 |                 : mAvailableOutputDevices.getDevicesFromTypeAddr(device, String8(address)); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4919 |         if (!deviceList.isEmpty()) { | 
 | 4920 |             struct audio_patch patch; | 
 | 4921 |             outputDesc->toAudioPortConfig(&patch.sources[0]); | 
 | 4922 |             patch.num_sources = 1; | 
 | 4923 |             patch.num_sinks = 0; | 
 | 4924 |             for (size_t i = 0; i < deviceList.size() && i < AUDIO_PATCH_PORTS_MAX; i++) { | 
 | 4925 |                 deviceList.itemAt(i)->toAudioPortConfig(&patch.sinks[i]); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4926 |                 patch.num_sinks++; | 
 | 4927 |             } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4928 |             ssize_t index; | 
 | 4929 |             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) { | 
 | 4930 |                 index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 4931 |             } else { | 
 | 4932 |                 index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 4933 |             } | 
 | 4934 |             sp< AudioPatch> patchDesc; | 
 | 4935 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 4936 |             if (index >= 0) { | 
 | 4937 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 4938 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 4939 |             } | 
 | 4940 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4941 |             status_t status = mpClientInterface->createAudioPatch(&patch, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4942 |                                                                    &afPatchHandle, | 
 | 4943 |                                                                    delayMs); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4944 |             ALOGV("setOutputDevice() createAudioPatch returned %d patchHandle %d" | 
 | 4945 |                     "num_sources %d num_sinks %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4946 |                                        status, afPatchHandle, patch.num_sources, patch.num_sinks); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4947 |             if (status == NO_ERROR) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4948 |                 if (index < 0) { | 
 | 4949 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 4950 |                                                &patch, mUidCached); | 
 | 4951 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 4952 |                 } else { | 
 | 4953 |                     patchDesc->mPatch = patch; | 
 | 4954 |                 } | 
 | 4955 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 4956 |                 patchDesc->mUid = mUidCached; | 
 | 4957 |                 if (patchHandle) { | 
 | 4958 |                     *patchHandle = patchDesc->mHandle; | 
 | 4959 |                 } | 
 | 4960 |                 outputDesc->mPatchHandle = patchDesc->mHandle; | 
 | 4961 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 4962 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4963 |             } | 
 | 4964 |         } | 
| bryant_liu | f5e7e79 | 2014-08-19 20:07:05 +0800 | [diff] [blame] | 4965 |  | 
 | 4966 |         // inform all input as well | 
 | 4967 |         for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 4968 |             const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i); | 
 | 4969 |             if (!isVirtualInputDevice(inputDescriptor->mDevice)) { | 
 | 4970 |                 AudioParameter inputCmd = AudioParameter(); | 
 | 4971 |                 ALOGV("%s: inform input %d of device:%d", __func__, | 
 | 4972 |                       inputDescriptor->mIoHandle, device); | 
 | 4973 |                 inputCmd.addInt(String8(AudioParameter::keyRouting),device); | 
 | 4974 |                 mpClientInterface->setParameters(inputDescriptor->mIoHandle, | 
 | 4975 |                                                  inputCmd.toString(), | 
 | 4976 |                                                  delayMs); | 
 | 4977 |             } | 
 | 4978 |         } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4979 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4980 |  | 
 | 4981 |     // update stream volumes according to new device | 
 | 4982 |     applyStreamVolumes(output, device, delayMs); | 
 | 4983 |  | 
 | 4984 |     return muteWaitMs; | 
 | 4985 | } | 
 | 4986 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4987 | status_t AudioPolicyManager::resetOutputDevice(audio_io_handle_t output, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4988 |                                                int delayMs, | 
 | 4989 |                                                audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4990 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4991 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4992 |     ssize_t index; | 
 | 4993 |     if (patchHandle) { | 
 | 4994 |         index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 4995 |     } else { | 
 | 4996 |         index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 4997 |     } | 
 | 4998 |     if (index < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4999 |         return INVALID_OPERATION; | 
 | 5000 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5001 |     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 5002 |     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5003 |     ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status); | 
 | 5004 |     outputDesc->mPatchHandle = 0; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5005 |     removeAudioPatch(patchDesc->mHandle); | 
 | 5006 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 5007 |     mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5008 |     return status; | 
 | 5009 | } | 
 | 5010 |  | 
 | 5011 | status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input, | 
 | 5012 |                                             audio_devices_t device, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5013 |                                             bool force, | 
 | 5014 |                                             audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5015 | { | 
 | 5016 |     status_t status = NO_ERROR; | 
 | 5017 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5018 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5019 |     if ((device != AUDIO_DEVICE_NONE) && ((device != inputDesc->mDevice) || force)) { | 
 | 5020 |         inputDesc->mDevice = device; | 
 | 5021 |  | 
 | 5022 |         DeviceVector deviceList = mAvailableInputDevices.getDevicesFromType(device); | 
 | 5023 |         if (!deviceList.isEmpty()) { | 
 | 5024 |             struct audio_patch patch; | 
 | 5025 |             inputDesc->toAudioPortConfig(&patch.sinks[0]); | 
| Eric Laurent | daf92cc | 2014-07-22 15:36:10 -0700 | [diff] [blame] | 5026 |             // AUDIO_SOURCE_HOTWORD is for internal use only: | 
 | 5027 |             // handled as AUDIO_SOURCE_VOICE_RECOGNITION by the audio HAL | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 5028 |             if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD && | 
 | 5029 |                     !inputDesc->mIsSoundTrigger) { | 
| Eric Laurent | daf92cc | 2014-07-22 15:36:10 -0700 | [diff] [blame] | 5030 |                 patch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_VOICE_RECOGNITION; | 
 | 5031 |             } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5032 |             patch.num_sinks = 1; | 
 | 5033 |             //only one input device for now | 
 | 5034 |             deviceList.itemAt(0)->toAudioPortConfig(&patch.sources[0]); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5035 |             patch.num_sources = 1; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5036 |             ssize_t index; | 
 | 5037 |             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) { | 
 | 5038 |                 index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 5039 |             } else { | 
 | 5040 |                 index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 5041 |             } | 
 | 5042 |             sp< AudioPatch> patchDesc; | 
 | 5043 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 5044 |             if (index >= 0) { | 
 | 5045 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 5046 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 5047 |             } | 
 | 5048 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5049 |             status_t status = mpClientInterface->createAudioPatch(&patch, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5050 |                                                                   &afPatchHandle, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5051 |                                                                   0); | 
 | 5052 |             ALOGV("setInputDevice() createAudioPatch returned %d patchHandle %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5053 |                                                                           status, afPatchHandle); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5054 |             if (status == NO_ERROR) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5055 |                 if (index < 0) { | 
 | 5056 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 5057 |                                                &patch, mUidCached); | 
 | 5058 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 5059 |                 } else { | 
 | 5060 |                     patchDesc->mPatch = patch; | 
 | 5061 |                 } | 
 | 5062 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 5063 |                 patchDesc->mUid = mUidCached; | 
 | 5064 |                 if (patchHandle) { | 
 | 5065 |                     *patchHandle = patchDesc->mHandle; | 
 | 5066 |                 } | 
 | 5067 |                 inputDesc->mPatchHandle = patchDesc->mHandle; | 
 | 5068 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 5069 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5070 |             } | 
 | 5071 |         } | 
 | 5072 |     } | 
 | 5073 |     return status; | 
 | 5074 | } | 
 | 5075 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5076 | status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input, | 
 | 5077 |                                               audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5078 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5079 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5080 |     ssize_t index; | 
 | 5081 |     if (patchHandle) { | 
 | 5082 |         index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 5083 |     } else { | 
 | 5084 |         index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 5085 |     } | 
 | 5086 |     if (index < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5087 |         return INVALID_OPERATION; | 
 | 5088 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5089 |     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 5090 |     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5091 |     ALOGV("resetInputDevice() releaseAudioPatch returned %d", status); | 
 | 5092 |     inputDesc->mPatchHandle = 0; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5093 |     removeAudioPatch(patchDesc->mHandle); | 
 | 5094 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 5095 |     mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5096 |     return status; | 
 | 5097 | } | 
 | 5098 |  | 
 | 5099 | sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device, | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5100 |                                                    String8 address, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5101 |                                                    uint32_t& samplingRate, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5102 |                                                    audio_format_t format, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 5103 |                                                    audio_channel_mask_t channelMask, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5104 |                                                    audio_input_flags_t flags) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5105 | { | 
 | 5106 |     // Choose an input profile based on the requested capture parameters: select the first available | 
 | 5107 |     // profile supporting all requested parameters. | 
 | 5108 |  | 
 | 5109 |     for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 5110 |     { | 
 | 5111 |         if (mHwModules[i]->mHandle == 0) { | 
 | 5112 |             continue; | 
 | 5113 |         } | 
 | 5114 |         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) | 
 | 5115 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5116 |             sp<IOProfile> profile = mHwModules[i]->mInputProfiles[j]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5117 |             // profile->log(); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5118 |             if (profile->isCompatibleProfile(device, address, samplingRate, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5119 |                                              &samplingRate /*updatedSamplingRate*/, | 
 | 5120 |                                              format, channelMask, (audio_output_flags_t) flags)) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5121 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5122 |                 return profile; | 
 | 5123 |             } | 
 | 5124 |         } | 
 | 5125 |     } | 
 | 5126 |     return NULL; | 
 | 5127 | } | 
 | 5128 |  | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 5129 |  | 
 | 5130 | audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource, | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 5131 |                                                             AudioMix **policyMix) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5132 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5133 |     audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & | 
 | 5134 |                                             ~AUDIO_DEVICE_BIT_IN; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5135 |  | 
 | 5136 |     for (size_t i = 0; i < mPolicyMixes.size(); i++) { | 
 | 5137 |         if (mPolicyMixes[i]->mMix.mMixType != MIX_TYPE_RECORDERS) { | 
 | 5138 |             continue; | 
 | 5139 |         } | 
 | 5140 |         for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) { | 
 | 5141 |             if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule && | 
 | 5142 |                     mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource == inputSource) || | 
 | 5143 |                (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule && | 
 | 5144 |                     mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource != inputSource)) { | 
 | 5145 |                 if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 5146 |                     if (policyMix != NULL) { | 
 | 5147 |                         *policyMix = &mPolicyMixes[i]->mMix; | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5148 |                     } | 
 | 5149 |                     return AUDIO_DEVICE_IN_REMOTE_SUBMIX; | 
 | 5150 |                 } | 
 | 5151 |                 break; | 
 | 5152 |             } | 
 | 5153 |         } | 
 | 5154 |     } | 
 | 5155 |  | 
| Eric Laurent | c73ca6e | 2014-12-12 14:34:22 -0800 | [diff] [blame] | 5156 |     return getDeviceForInputSource(inputSource); | 
 | 5157 | } | 
 | 5158 |  | 
 | 5159 | audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource) | 
 | 5160 | { | 
 | 5161 |     uint32_t device = AUDIO_DEVICE_NONE; | 
 | 5162 |     audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & | 
 | 5163 |                                             ~AUDIO_DEVICE_BIT_IN; | 
 | 5164 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5165 |     switch (inputSource) { | 
 | 5166 |     case AUDIO_SOURCE_VOICE_UPLINK: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5167 |       if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5168 |           device = AUDIO_DEVICE_IN_VOICE_CALL; | 
 | 5169 |           break; | 
 | 5170 |       } | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 5171 |       break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5172 |  | 
 | 5173 |     case AUDIO_SOURCE_DEFAULT: | 
 | 5174 |     case AUDIO_SOURCE_MIC: | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 5175 |     if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) { | 
 | 5176 |         device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP; | 
| Eric Laurent | dc136ff | 2014-12-16 12:24:18 -0800 | [diff] [blame] | 5177 |     } else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) && | 
 | 5178 |         (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) { | 
 | 5179 |         device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 5180 |     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { | 
 | 5181 |         device = AUDIO_DEVICE_IN_WIRED_HEADSET; | 
 | 5182 |     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { | 
 | 5183 |         device = AUDIO_DEVICE_IN_USB_DEVICE; | 
 | 5184 |     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
 | 5185 |         device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 5186 |     } | 
| Eric Laurent | c2730ba | 2014-07-20 15:47:07 -0700 | [diff] [blame] | 5187 |     break; | 
 | 5188 |  | 
 | 5189 |     case AUDIO_SOURCE_VOICE_COMMUNICATION: | 
 | 5190 |         // Allow only use of devices on primary input if in call and HAL does not support routing | 
 | 5191 |         // to voice call path. | 
 | 5192 |         if ((mPhoneState == AUDIO_MODE_IN_CALL) && | 
 | 5193 |                 (mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) { | 
 | 5194 |             availableDeviceTypes = availablePrimaryInputDevices() & ~AUDIO_DEVICE_BIT_IN; | 
 | 5195 |         } | 
 | 5196 |  | 
 | 5197 |         switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) { | 
 | 5198 |         case AUDIO_POLICY_FORCE_BT_SCO: | 
 | 5199 |             // if SCO device is requested but no SCO device is available, fall back to default case | 
 | 5200 |             if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { | 
 | 5201 |                 device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; | 
 | 5202 |                 break; | 
 | 5203 |             } | 
 | 5204 |             // FALL THROUGH | 
 | 5205 |  | 
 | 5206 |         default:    // FORCE_NONE | 
 | 5207 |             if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { | 
 | 5208 |                 device = AUDIO_DEVICE_IN_WIRED_HEADSET; | 
 | 5209 |             } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { | 
 | 5210 |                 device = AUDIO_DEVICE_IN_USB_DEVICE; | 
 | 5211 |             } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
 | 5212 |                 device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 5213 |             } | 
 | 5214 |             break; | 
 | 5215 |  | 
 | 5216 |         case AUDIO_POLICY_FORCE_SPEAKER: | 
 | 5217 |             if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { | 
 | 5218 |                 device = AUDIO_DEVICE_IN_BACK_MIC; | 
 | 5219 |             } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
 | 5220 |                 device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 5221 |             } | 
 | 5222 |             break; | 
 | 5223 |         } | 
 | 5224 |         break; | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 5225 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5226 |     case AUDIO_SOURCE_VOICE_RECOGNITION: | 
 | 5227 |     case AUDIO_SOURCE_HOTWORD: | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5228 |         if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5229 |                 availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5230 |             device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5231 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5232 |             device = AUDIO_DEVICE_IN_WIRED_HEADSET; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5233 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { | 
 | 5234 |             device = AUDIO_DEVICE_IN_USB_DEVICE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5235 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5236 |             device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 5237 |         } | 
 | 5238 |         break; | 
 | 5239 |     case AUDIO_SOURCE_CAMCORDER: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5240 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5241 |             device = AUDIO_DEVICE_IN_BACK_MIC; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5242 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5243 |             device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 5244 |         } | 
 | 5245 |         break; | 
 | 5246 |     case AUDIO_SOURCE_VOICE_DOWNLINK: | 
 | 5247 |     case AUDIO_SOURCE_VOICE_CALL: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5248 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5249 |             device = AUDIO_DEVICE_IN_VOICE_CALL; | 
 | 5250 |         } | 
 | 5251 |         break; | 
 | 5252 |     case AUDIO_SOURCE_REMOTE_SUBMIX: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5253 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5254 |             device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; | 
 | 5255 |         } | 
 | 5256 |         break; | 
| Hochi Huang | 327cb70 | 2014-09-21 09:47:31 +0800 | [diff] [blame] | 5257 |      case AUDIO_SOURCE_FM_TUNER: | 
 | 5258 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) { | 
 | 5259 |             device = AUDIO_DEVICE_IN_FM_TUNER; | 
 | 5260 |         } | 
 | 5261 |         break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5262 |     default: | 
 | 5263 |         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource); | 
 | 5264 |         break; | 
 | 5265 |     } | 
 | 5266 |     ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); | 
 | 5267 |     return device; | 
 | 5268 | } | 
 | 5269 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5270 | bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5271 | { | 
 | 5272 |     if ((device & AUDIO_DEVICE_BIT_IN) != 0) { | 
 | 5273 |         device &= ~AUDIO_DEVICE_BIT_IN; | 
 | 5274 |         if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0)) | 
 | 5275 |             return true; | 
 | 5276 |     } | 
 | 5277 |     return false; | 
 | 5278 | } | 
 | 5279 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 5280 | bool AudioPolicyManager::deviceDistinguishesOnAddress(audio_devices_t device) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5281 |     return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 5282 | } | 
 | 5283 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5284 | audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5285 | { | 
 | 5286 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5287 |         const sp<AudioInputDescriptor>  input_descriptor = mInputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5288 |         if ((input_descriptor->mRefCount > 0) | 
 | 5289 |                 && (!ignoreVirtualInputs || !isVirtualInputDevice(input_descriptor->mDevice))) { | 
 | 5290 |             return mInputs.keyAt(i); | 
 | 5291 |         } | 
 | 5292 |     } | 
 | 5293 |     return 0; | 
 | 5294 | } | 
 | 5295 |  | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 5296 | uint32_t AudioPolicyManager::activeInputsCount() const | 
 | 5297 | { | 
 | 5298 |     uint32_t count = 0; | 
 | 5299 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 5300 |         const sp<AudioInputDescriptor>  desc = mInputs.valueAt(i); | 
 | 5301 |         if (desc->mRefCount > 0) { | 
| Eric Laurent | a34c9ce | 2014-12-19 11:16:32 -0800 | [diff] [blame] | 5302 |             count++; | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 5303 |         } | 
 | 5304 |     } | 
 | 5305 |     return count; | 
 | 5306 | } | 
 | 5307 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5308 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5309 | audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5310 | { | 
 | 5311 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 5312 |         // this happens when forcing a route update and no track is active on an output. | 
 | 5313 |         // In this case the returned category is not important. | 
 | 5314 |         device =  AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5315 |     } else if (popcount(device) > 1) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5316 |         // Multiple device selection is either: | 
 | 5317 |         //  - speaker + one other device: give priority to speaker in this case. | 
 | 5318 |         //  - one A2DP device + another device: happens with duplicated output. In this case | 
 | 5319 |         // retain the device on the A2DP output as the other must not correspond to an active | 
 | 5320 |         // selection if not the speaker. | 
| Jungshik Jang | a1f9917 | 2014-09-05 21:25:48 +0900 | [diff] [blame] | 5321 |         //  - HDMI-CEC system audio mode only output: give priority to available item in order. | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5322 |         if (device & AUDIO_DEVICE_OUT_SPEAKER) { | 
 | 5323 |             device = AUDIO_DEVICE_OUT_SPEAKER; | 
| Jungshik Jang | a1f9917 | 2014-09-05 21:25:48 +0900 | [diff] [blame] | 5324 |         } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) { | 
 | 5325 |             device = AUDIO_DEVICE_OUT_HDMI_ARC; | 
 | 5326 |         } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) { | 
 | 5327 |             device = AUDIO_DEVICE_OUT_AUX_LINE; | 
 | 5328 |         } else if (device & AUDIO_DEVICE_OUT_SPDIF) { | 
 | 5329 |             device = AUDIO_DEVICE_OUT_SPDIF; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5330 |         } else { | 
 | 5331 |             device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP); | 
 | 5332 |         } | 
 | 5333 |     } | 
 | 5334 |  | 
| Jon Eklund | 11c9fb1 | 2014-06-23 14:47:03 -0500 | [diff] [blame] | 5335 |     /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/ | 
 | 5336 |     if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE) | 
 | 5337 |         device = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 5338 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5339 |     ALOGW_IF(popcount(device) != 1, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5340 |             "getDeviceForVolume() invalid device combination: %08x", | 
 | 5341 |             device); | 
 | 5342 |  | 
 | 5343 |     return device; | 
 | 5344 | } | 
 | 5345 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5346 | AudioPolicyManager::device_category AudioPolicyManager::getDeviceCategory(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5347 | { | 
 | 5348 |     switch(getDeviceForVolume(device)) { | 
 | 5349 |         case AUDIO_DEVICE_OUT_EARPIECE: | 
 | 5350 |             return DEVICE_CATEGORY_EARPIECE; | 
 | 5351 |         case AUDIO_DEVICE_OUT_WIRED_HEADSET: | 
 | 5352 |         case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: | 
 | 5353 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO: | 
 | 5354 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: | 
 | 5355 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: | 
 | 5356 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: | 
 | 5357 |             return DEVICE_CATEGORY_HEADSET; | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5358 |         case AUDIO_DEVICE_OUT_LINE: | 
 | 5359 |         case AUDIO_DEVICE_OUT_AUX_DIGITAL: | 
 | 5360 |         /*USB?  Remote submix?*/ | 
 | 5361 |             return DEVICE_CATEGORY_EXT_MEDIA; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5362 |         case AUDIO_DEVICE_OUT_SPEAKER: | 
 | 5363 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: | 
 | 5364 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5365 |         case AUDIO_DEVICE_OUT_USB_ACCESSORY: | 
 | 5366 |         case AUDIO_DEVICE_OUT_USB_DEVICE: | 
 | 5367 |         case AUDIO_DEVICE_OUT_REMOTE_SUBMIX: | 
 | 5368 |         default: | 
 | 5369 |             return DEVICE_CATEGORY_SPEAKER; | 
 | 5370 |     } | 
 | 5371 | } | 
 | 5372 |  | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5373 | /* static */ | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5374 | float AudioPolicyManager::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5375 |         int indexInUi) | 
 | 5376 | { | 
 | 5377 |     device_category deviceCategory = getDeviceCategory(device); | 
 | 5378 |     const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory]; | 
 | 5379 |  | 
 | 5380 |     // the volume index in the UI is relative to the min and max volume indices for this stream type | 
 | 5381 |     int nbSteps = 1 + curve[VOLMAX].mIndex - | 
 | 5382 |             curve[VOLMIN].mIndex; | 
 | 5383 |     int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) / | 
 | 5384 |             (streamDesc.mIndexMax - streamDesc.mIndexMin); | 
 | 5385 |  | 
 | 5386 |     // find what part of the curve this index volume belongs to, or if it's out of bounds | 
 | 5387 |     int segment = 0; | 
 | 5388 |     if (volIdx < curve[VOLMIN].mIndex) {         // out of bounds | 
 | 5389 |         return 0.0f; | 
 | 5390 |     } else if (volIdx < curve[VOLKNEE1].mIndex) { | 
 | 5391 |         segment = 0; | 
 | 5392 |     } else if (volIdx < curve[VOLKNEE2].mIndex) { | 
 | 5393 |         segment = 1; | 
 | 5394 |     } else if (volIdx <= curve[VOLMAX].mIndex) { | 
 | 5395 |         segment = 2; | 
 | 5396 |     } else {                                                               // out of bounds | 
 | 5397 |         return 1.0f; | 
 | 5398 |     } | 
 | 5399 |  | 
 | 5400 |     // linear interpolation in the attenuation table in dB | 
 | 5401 |     float decibels = curve[segment].mDBAttenuation + | 
 | 5402 |             ((float)(volIdx - curve[segment].mIndex)) * | 
 | 5403 |                 ( (curve[segment+1].mDBAttenuation - | 
 | 5404 |                         curve[segment].mDBAttenuation) / | 
 | 5405 |                     ((float)(curve[segment+1].mIndex - | 
 | 5406 |                             curve[segment].mIndex)) ); | 
 | 5407 |  | 
 | 5408 |     float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) | 
 | 5409 |  | 
 | 5410 |     ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", | 
 | 5411 |             curve[segment].mIndex, volIdx, | 
 | 5412 |             curve[segment+1].mIndex, | 
 | 5413 |             curve[segment].mDBAttenuation, | 
 | 5414 |             decibels, | 
 | 5415 |             curve[segment+1].mDBAttenuation, | 
 | 5416 |             amplification); | 
 | 5417 |  | 
 | 5418 |     return amplification; | 
 | 5419 | } | 
 | 5420 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5421 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5422 |     AudioPolicyManager::sDefaultVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5423 |     {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f} | 
 | 5424 | }; | 
 | 5425 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5426 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5427 |     AudioPolicyManager::sDefaultMediaVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5428 |     {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f} | 
 | 5429 | }; | 
 | 5430 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5431 | const AudioPolicyManager::VolumeCurvePoint | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5432 |     AudioPolicyManager::sExtMediaSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
 | 5433 |     {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f} | 
 | 5434 | }; | 
 | 5435 |  | 
 | 5436 | const AudioPolicyManager::VolumeCurvePoint | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5437 |     AudioPolicyManager::sSpeakerMediaVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5438 |     {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f} | 
 | 5439 | }; | 
 | 5440 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5441 | const AudioPolicyManager::VolumeCurvePoint | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 5442 |     AudioPolicyManager::sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Jean-Michel Trivi | 98c6043 | 2014-07-09 08:51:34 -0700 | [diff] [blame] | 5443 |     {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f} | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 5444 | }; | 
 | 5445 |  | 
 | 5446 | const AudioPolicyManager::VolumeCurvePoint | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5447 |     AudioPolicyManager::sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5448 |     {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f} | 
 | 5449 | }; | 
 | 5450 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5451 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5452 |     AudioPolicyManager::sSpeakerSonificationVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5453 |     {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f} | 
 | 5454 | }; | 
 | 5455 |  | 
 | 5456 | // AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks | 
 | 5457 | // AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets. | 
 | 5458 | // AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java). | 
 | 5459 | // The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset. | 
 | 5460 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5461 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5462 |     AudioPolicyManager::sDefaultSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5463 |     {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f} | 
 | 5464 | }; | 
 | 5465 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5466 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5467 |     AudioPolicyManager::sDefaultSystemVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5468 |     {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f} | 
 | 5469 | }; | 
 | 5470 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5471 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5472 |     AudioPolicyManager::sHeadsetSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5473 |     {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f} | 
 | 5474 | }; | 
 | 5475 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5476 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5477 |     AudioPolicyManager::sDefaultVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5478 |     {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f} | 
 | 5479 | }; | 
 | 5480 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5481 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5482 |     AudioPolicyManager::sSpeakerVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5483 |     {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f} | 
 | 5484 | }; | 
 | 5485 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5486 | const AudioPolicyManager::VolumeCurvePoint | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 5487 |     AudioPolicyManager::sLinearVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
 | 5488 |     {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f} | 
 | 5489 | }; | 
 | 5490 |  | 
 | 5491 | const AudioPolicyManager::VolumeCurvePoint | 
 | 5492 |     AudioPolicyManager::sSilentVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
 | 5493 |     {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f} | 
 | 5494 | }; | 
 | 5495 |  | 
 | 5496 | const AudioPolicyManager::VolumeCurvePoint | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5497 |     AudioPolicyManager::sFullScaleVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
 | 5498 |     {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f} | 
 | 5499 | }; | 
 | 5500 |  | 
 | 5501 | const AudioPolicyManager::VolumeCurvePoint | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5502 |             *AudioPolicyManager::sVolumeProfiles[AUDIO_STREAM_CNT] | 
 | 5503 |                                                    [AudioPolicyManager::DEVICE_CATEGORY_CNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5504 |     { // AUDIO_STREAM_VOICE_CALL | 
 | 5505 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5506 |         sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5507 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5508 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5509 |     }, | 
 | 5510 |     { // AUDIO_STREAM_SYSTEM | 
 | 5511 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5512 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5513 |         sDefaultSystemVolumeCurve,  // DEVICE_CATEGORY_EARPIECE | 
 | 5514 |         sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5515 |     }, | 
 | 5516 |     { // AUDIO_STREAM_RING | 
 | 5517 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5518 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5519 |         sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE | 
 | 5520 |         sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5521 |     }, | 
 | 5522 |     { // AUDIO_STREAM_MUSIC | 
 | 5523 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5524 |         sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5525 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5526 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5527 |     }, | 
 | 5528 |     { // AUDIO_STREAM_ALARM | 
 | 5529 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5530 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5531 |         sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE | 
 | 5532 |         sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5533 |     }, | 
 | 5534 |     { // AUDIO_STREAM_NOTIFICATION | 
 | 5535 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5536 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5537 |         sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE | 
 | 5538 |         sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5539 |     }, | 
 | 5540 |     { // AUDIO_STREAM_BLUETOOTH_SCO | 
 | 5541 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5542 |         sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5543 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5544 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5545 |     }, | 
 | 5546 |     { // AUDIO_STREAM_ENFORCED_AUDIBLE | 
 | 5547 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5548 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5549 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5550 |         sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5551 |     }, | 
 | 5552 |     {  // AUDIO_STREAM_DTMF | 
 | 5553 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5554 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
| Jon Eklund | ac29afa | 2014-07-28 16:06:06 -0500 | [diff] [blame] | 5555 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5556 |         sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5557 |     }, | 
 | 5558 |     { // AUDIO_STREAM_TTS | 
| Jean-Michel Trivi | d9cfeb4 | 2014-09-22 16:51:34 -0700 | [diff] [blame] | 5559 |       // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER | 
 | 5560 |         sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5561 |         sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 5562 |         sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5563 |         sSilentVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5564 |     }, | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5565 |     { // AUDIO_STREAM_ACCESSIBILITY | 
 | 5566 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5567 |         sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 5568 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5569 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
 | 5570 |     }, | 
 | 5571 |     { // AUDIO_STREAM_REROUTING | 
 | 5572 |         sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5573 |         sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 5574 |         sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5575 |         sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
 | 5576 |     }, | 
 | 5577 |     { // AUDIO_STREAM_PATCH | 
 | 5578 |         sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 5579 |         sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 5580 |         sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE | 
 | 5581 |         sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA | 
 | 5582 |     }, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5583 | }; | 
 | 5584 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5585 | void AudioPolicyManager::initializeVolumeCurves() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5586 | { | 
 | 5587 |     for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
 | 5588 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 5589 |             mStreams[i].mVolumeCurve[j] = | 
 | 5590 |                     sVolumeProfiles[i][j]; | 
 | 5591 |         } | 
 | 5592 |     } | 
 | 5593 |  | 
 | 5594 |     // Check availability of DRC on speaker path: if available, override some of the speaker curves | 
 | 5595 |     if (mSpeakerDrcEnabled) { | 
 | 5596 |         mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 5597 |                 sDefaultSystemVolumeCurveDrc; | 
 | 5598 |         mStreams[AUDIO_STREAM_RING].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 5599 |                 sSpeakerSonificationVolumeCurveDrc; | 
 | 5600 |         mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 5601 |                 sSpeakerSonificationVolumeCurveDrc; | 
 | 5602 |         mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 5603 |                 sSpeakerSonificationVolumeCurveDrc; | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 5604 |         mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 5605 |                 sSpeakerMediaVolumeCurveDrc; | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5606 |         mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 5607 |                 sSpeakerMediaVolumeCurveDrc; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5608 |     } | 
 | 5609 | } | 
 | 5610 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5611 | float AudioPolicyManager::computeVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5612 |                                             int index, | 
 | 5613 |                                             audio_io_handle_t output, | 
 | 5614 |                                             audio_devices_t device) | 
 | 5615 | { | 
 | 5616 |     float volume = 1.0; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5617 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5618 |     StreamDescriptor &streamDesc = mStreams[stream]; | 
 | 5619 |  | 
 | 5620 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 5621 |         device = outputDesc->device(); | 
 | 5622 |     } | 
 | 5623 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5624 |     volume = volIndexToAmpl(device, streamDesc, index); | 
 | 5625 |  | 
 | 5626 |     // if a headset is connected, apply the following rules to ring tones and notifications | 
 | 5627 |     // to avoid sound level bursts in user's ears: | 
 | 5628 |     // - always attenuate ring tones and notifications volume by 6dB | 
 | 5629 |     // - if music is playing, always limit the volume to current music volume, | 
 | 5630 |     // with a minimum threshold at -36dB so that notification is always perceived. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5631 |     const routing_strategy stream_strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5632 |     if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | | 
 | 5633 |             AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | | 
 | 5634 |             AUDIO_DEVICE_OUT_WIRED_HEADSET | | 
 | 5635 |             AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) && | 
 | 5636 |         ((stream_strategy == STRATEGY_SONIFICATION) | 
 | 5637 |                 || (stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL) | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5638 |                 || (stream == AUDIO_STREAM_SYSTEM) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5639 |                 || ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5640 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5641 |         streamDesc.mCanBeMuted) { | 
 | 5642 |         volume *= SONIFICATION_HEADSET_VOLUME_FACTOR; | 
 | 5643 |         // when the phone is ringing we must consider that music could have been paused just before | 
 | 5644 |         // by the music application and behave as if music was active if the last music track was | 
 | 5645 |         // just stopped | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5646 |         if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5647 |                 mLimitRingtoneVolume) { | 
 | 5648 |             audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5649 |             float musicVol = computeVolume(AUDIO_STREAM_MUSIC, | 
 | 5650 |                                mStreams[AUDIO_STREAM_MUSIC].getVolumeIndex(musicDevice), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5651 |                                output, | 
 | 5652 |                                musicDevice); | 
 | 5653 |             float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? | 
 | 5654 |                                 musicVol : SONIFICATION_HEADSET_VOLUME_MIN; | 
 | 5655 |             if (volume > minVol) { | 
 | 5656 |                 volume = minVol; | 
 | 5657 |                 ALOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol); | 
 | 5658 |             } | 
 | 5659 |         } | 
 | 5660 |     } | 
 | 5661 |  | 
 | 5662 |     return volume; | 
 | 5663 | } | 
 | 5664 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5665 | status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5666 |                                                    int index, | 
 | 5667 |                                                    audio_io_handle_t output, | 
 | 5668 |                                                    audio_devices_t device, | 
 | 5669 |                                                    int delayMs, | 
 | 5670 |                                                    bool force) | 
 | 5671 | { | 
 | 5672 |  | 
 | 5673 |     // do not change actual stream volume if the stream is muted | 
 | 5674 |     if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { | 
 | 5675 |         ALOGVV("checkAndSetVolume() stream %d muted count %d", | 
 | 5676 |               stream, mOutputs.valueFor(output)->mMuteCount[stream]); | 
 | 5677 |         return NO_ERROR; | 
 | 5678 |     } | 
 | 5679 |  | 
 | 5680 |     // do not change in call volume if bluetooth is connected and vice versa | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5681 |     if ((stream == AUDIO_STREAM_VOICE_CALL && | 
 | 5682 |             mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) || | 
 | 5683 |         (stream == AUDIO_STREAM_BLUETOOTH_SCO && | 
 | 5684 |                 mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5685 |         ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm", | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5686 |              stream, mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5687 |         return INVALID_OPERATION; | 
 | 5688 |     } | 
 | 5689 |  | 
 | 5690 |     float volume = computeVolume(stream, index, output, device); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5691 |     // unit gain if rerouting to external policy | 
 | 5692 |     if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) { | 
 | 5693 |         ssize_t index = mOutputs.indexOfKey(output); | 
 | 5694 |         if (index >= 0) { | 
 | 5695 |             sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 5696 |             if (outputDesc->mPolicyMix != NULL) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5697 |                 ALOGV("max gain when rerouting for output=%d", output); | 
 | 5698 |                 volume = 1.0f; | 
 | 5699 |             } | 
 | 5700 |         } | 
 | 5701 |  | 
 | 5702 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5703 |     // We actually change the volume if: | 
 | 5704 |     // - the float value returned by computeVolume() changed | 
 | 5705 |     // - the force flag is set | 
 | 5706 |     if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || | 
 | 5707 |             force) { | 
 | 5708 |         mOutputs.valueFor(output)->mCurVolume[stream] = volume; | 
 | 5709 |         ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); | 
 | 5710 |         // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is | 
 | 5711 |         // enabled | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5712 |         if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { | 
 | 5713 |             mpClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume, output, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5714 |         } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5715 |         mpClientInterface->setStreamVolume(stream, volume, output, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5716 |     } | 
 | 5717 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5718 |     if (stream == AUDIO_STREAM_VOICE_CALL || | 
 | 5719 |         stream == AUDIO_STREAM_BLUETOOTH_SCO) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5720 |         float voiceVolume; | 
 | 5721 |         // Force voice volume to max for bluetooth SCO as volume is managed by the headset | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5722 |         if (stream == AUDIO_STREAM_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5723 |             voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; | 
 | 5724 |         } else { | 
 | 5725 |             voiceVolume = 1.0; | 
 | 5726 |         } | 
 | 5727 |  | 
 | 5728 |         if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) { | 
 | 5729 |             mpClientInterface->setVoiceVolume(voiceVolume, delayMs); | 
 | 5730 |             mLastVoiceVolume = voiceVolume; | 
 | 5731 |         } | 
 | 5732 |     } | 
 | 5733 |  | 
 | 5734 |     return NO_ERROR; | 
 | 5735 | } | 
 | 5736 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5737 | void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5738 |                                                 audio_devices_t device, | 
 | 5739 |                                                 int delayMs, | 
 | 5740 |                                                 bool force) | 
 | 5741 | { | 
 | 5742 |     ALOGVV("applyStreamVolumes() for output %d and device %x", output, device); | 
 | 5743 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5744 |     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5745 |         if (stream == AUDIO_STREAM_PATCH) { | 
 | 5746 |             continue; | 
 | 5747 |         } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5748 |         checkAndSetVolume((audio_stream_type_t)stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5749 |                           mStreams[stream].getVolumeIndex(device), | 
 | 5750 |                           output, | 
 | 5751 |                           device, | 
 | 5752 |                           delayMs, | 
 | 5753 |                           force); | 
 | 5754 |     } | 
 | 5755 | } | 
 | 5756 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5757 | void AudioPolicyManager::setStrategyMute(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5758 |                                              bool on, | 
 | 5759 |                                              audio_io_handle_t output, | 
 | 5760 |                                              int delayMs, | 
 | 5761 |                                              audio_devices_t device) | 
 | 5762 | { | 
 | 5763 |     ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5764 |     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5765 |         if (stream == AUDIO_STREAM_PATCH) { | 
 | 5766 |             continue; | 
 | 5767 |         } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5768 |         if (getStrategy((audio_stream_type_t)stream) == strategy) { | 
 | 5769 |             setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5770 |         } | 
 | 5771 |     } | 
 | 5772 | } | 
 | 5773 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5774 | void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5775 |                                            bool on, | 
 | 5776 |                                            audio_io_handle_t output, | 
 | 5777 |                                            int delayMs, | 
 | 5778 |                                            audio_devices_t device) | 
 | 5779 | { | 
 | 5780 |     StreamDescriptor &streamDesc = mStreams[stream]; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5781 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5782 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 5783 |         device = outputDesc->device(); | 
 | 5784 |     } | 
 | 5785 |  | 
 | 5786 |     ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x", | 
 | 5787 |           stream, on, output, outputDesc->mMuteCount[stream], device); | 
 | 5788 |  | 
 | 5789 |     if (on) { | 
 | 5790 |         if (outputDesc->mMuteCount[stream] == 0) { | 
 | 5791 |             if (streamDesc.mCanBeMuted && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5792 |                     ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) || | 
 | 5793 |                      (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5794 |                 checkAndSetVolume(stream, 0, output, device, delayMs); | 
 | 5795 |             } | 
 | 5796 |         } | 
 | 5797 |         // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored | 
 | 5798 |         outputDesc->mMuteCount[stream]++; | 
 | 5799 |     } else { | 
 | 5800 |         if (outputDesc->mMuteCount[stream] == 0) { | 
 | 5801 |             ALOGV("setStreamMute() unmuting non muted stream!"); | 
 | 5802 |             return; | 
 | 5803 |         } | 
 | 5804 |         if (--outputDesc->mMuteCount[stream] == 0) { | 
 | 5805 |             checkAndSetVolume(stream, | 
 | 5806 |                               streamDesc.getVolumeIndex(device), | 
 | 5807 |                               output, | 
 | 5808 |                               device, | 
 | 5809 |                               delayMs); | 
 | 5810 |         } | 
 | 5811 |     } | 
 | 5812 | } | 
 | 5813 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5814 | void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5815 |                                                       bool starting, bool stateChange) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5816 | { | 
 | 5817 |     // if the stream pertains to sonification strategy and we are in call we must | 
 | 5818 |     // mute the stream if it is low visibility. If it is high visibility, we must play a tone | 
 | 5819 |     // in the device used for phone strategy and play the tone if the selected device does not | 
 | 5820 |     // interfere with the device used for phone strategy | 
 | 5821 |     // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as | 
 | 5822 |     // many times as there are active tracks on the output | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5823 |     const routing_strategy stream_strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5824 |     if ((stream_strategy == STRATEGY_SONIFICATION) || | 
 | 5825 |             ((stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL))) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5826 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5827 |         ALOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d", | 
 | 5828 |                 stream, starting, outputDesc->mDevice, stateChange); | 
 | 5829 |         if (outputDesc->mRefCount[stream]) { | 
 | 5830 |             int muteCount = 1; | 
 | 5831 |             if (stateChange) { | 
 | 5832 |                 muteCount = outputDesc->mRefCount[stream]; | 
 | 5833 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5834 |             if (audio_is_low_visibility(stream)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5835 |                 ALOGV("handleIncallSonification() low visibility, muteCount %d", muteCount); | 
 | 5836 |                 for (int i = 0; i < muteCount; i++) { | 
 | 5837 |                     setStreamMute(stream, starting, mPrimaryOutput); | 
 | 5838 |                 } | 
 | 5839 |             } else { | 
 | 5840 |                 ALOGV("handleIncallSonification() high visibility"); | 
 | 5841 |                 if (outputDesc->device() & | 
 | 5842 |                         getDeviceForStrategy(STRATEGY_PHONE, true /*fromCache*/)) { | 
 | 5843 |                     ALOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount); | 
 | 5844 |                     for (int i = 0; i < muteCount; i++) { | 
 | 5845 |                         setStreamMute(stream, starting, mPrimaryOutput); | 
 | 5846 |                     } | 
 | 5847 |                 } | 
 | 5848 |                 if (starting) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5849 |                     mpClientInterface->startTone(AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION, | 
 | 5850 |                                                  AUDIO_STREAM_VOICE_CALL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5851 |                 } else { | 
 | 5852 |                     mpClientInterface->stopTone(); | 
 | 5853 |                 } | 
 | 5854 |             } | 
 | 5855 |         } | 
 | 5856 |     } | 
 | 5857 | } | 
 | 5858 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5859 | bool AudioPolicyManager::isInCall() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5860 | { | 
 | 5861 |     return isStateInCall(mPhoneState); | 
 | 5862 | } | 
 | 5863 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5864 | bool AudioPolicyManager::isStateInCall(int state) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5865 |     return ((state == AUDIO_MODE_IN_CALL) || | 
 | 5866 |             (state == AUDIO_MODE_IN_COMMUNICATION)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5867 | } | 
 | 5868 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5869 | uint32_t AudioPolicyManager::getMaxEffectsCpuLoad() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5870 | { | 
 | 5871 |     return MAX_EFFECTS_CPU_LOAD; | 
 | 5872 | } | 
 | 5873 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5874 | uint32_t AudioPolicyManager::getMaxEffectsMemory() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5875 | { | 
 | 5876 |     return MAX_EFFECTS_MEMORY; | 
 | 5877 | } | 
 | 5878 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5879 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5880 | // --- AudioOutputDescriptor class implementation | 
 | 5881 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5882 | AudioPolicyManager::AudioOutputDescriptor::AudioOutputDescriptor( | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5883 |         const sp<IOProfile>& profile) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5884 |     : mId(0), mIoHandle(0), mLatency(0), | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 5885 |     mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 5886 |     mPatchHandle(0), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5887 |     mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0) | 
 | 5888 | { | 
 | 5889 |     // clear usage count for all stream types | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5890 |     for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5891 |         mRefCount[i] = 0; | 
 | 5892 |         mCurVolume[i] = -1.0; | 
 | 5893 |         mMuteCount[i] = 0; | 
 | 5894 |         mStopTime[i] = 0; | 
 | 5895 |     } | 
 | 5896 |     for (int i = 0; i < NUM_STRATEGIES; i++) { | 
 | 5897 |         mStrategyMutedByDevice[i] = false; | 
 | 5898 |     } | 
 | 5899 |     if (profile != NULL) { | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 5900 |         mFlags = (audio_output_flags_t)profile->mFlags; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5901 |         mSamplingRate = profile->pickSamplingRate(); | 
 | 5902 |         mFormat = profile->pickFormat(); | 
 | 5903 |         mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5904 |         if (profile->mGains.size() > 0) { | 
 | 5905 |             profile->mGains[0]->getDefaultConfig(&mGain); | 
 | 5906 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5907 |     } | 
 | 5908 | } | 
 | 5909 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5910 | audio_devices_t AudioPolicyManager::AudioOutputDescriptor::device() const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5911 | { | 
 | 5912 |     if (isDuplicated()) { | 
 | 5913 |         return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); | 
 | 5914 |     } else { | 
 | 5915 |         return mDevice; | 
 | 5916 |     } | 
 | 5917 | } | 
 | 5918 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5919 | uint32_t AudioPolicyManager::AudioOutputDescriptor::latency() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5920 | { | 
 | 5921 |     if (isDuplicated()) { | 
 | 5922 |         return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; | 
 | 5923 |     } else { | 
 | 5924 |         return mLatency; | 
 | 5925 |     } | 
 | 5926 | } | 
 | 5927 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5928 | bool AudioPolicyManager::AudioOutputDescriptor::sharesHwModuleWith( | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5929 |         const sp<AudioOutputDescriptor> outputDesc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5930 | { | 
 | 5931 |     if (isDuplicated()) { | 
 | 5932 |         return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); | 
 | 5933 |     } else if (outputDesc->isDuplicated()){ | 
 | 5934 |         return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); | 
 | 5935 |     } else { | 
 | 5936 |         return (mProfile->mModule == outputDesc->mProfile->mModule); | 
 | 5937 |     } | 
 | 5938 | } | 
 | 5939 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5940 | void AudioPolicyManager::AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5941 |                                                                    int delta) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5942 | { | 
 | 5943 |     // forward usage count change to attached outputs | 
 | 5944 |     if (isDuplicated()) { | 
 | 5945 |         mOutput1->changeRefCount(stream, delta); | 
 | 5946 |         mOutput2->changeRefCount(stream, delta); | 
 | 5947 |     } | 
 | 5948 |     if ((delta + (int)mRefCount[stream]) < 0) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5949 |         ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", | 
 | 5950 |               delta, stream, mRefCount[stream]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5951 |         mRefCount[stream] = 0; | 
 | 5952 |         return; | 
 | 5953 |     } | 
 | 5954 |     mRefCount[stream] += delta; | 
 | 5955 |     ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); | 
 | 5956 | } | 
 | 5957 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5958 | audio_devices_t AudioPolicyManager::AudioOutputDescriptor::supportedDevices() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5959 | { | 
 | 5960 |     if (isDuplicated()) { | 
 | 5961 |         return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); | 
 | 5962 |     } else { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5963 |         return mProfile->mSupportedDevices.types() ; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5964 |     } | 
 | 5965 | } | 
 | 5966 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5967 | bool AudioPolicyManager::AudioOutputDescriptor::isActive(uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5968 | { | 
 | 5969 |     return isStrategyActive(NUM_STRATEGIES, inPastMs); | 
 | 5970 | } | 
 | 5971 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5972 | bool AudioPolicyManager::AudioOutputDescriptor::isStrategyActive(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5973 |                                                                        uint32_t inPastMs, | 
 | 5974 |                                                                        nsecs_t sysTime) const | 
 | 5975 | { | 
 | 5976 |     if ((sysTime == 0) && (inPastMs != 0)) { | 
 | 5977 |         sysTime = systemTime(); | 
 | 5978 |     } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5979 |     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 5980 |         if (i == AUDIO_STREAM_PATCH) { | 
 | 5981 |             continue; | 
 | 5982 |         } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5983 |         if (((getStrategy((audio_stream_type_t)i) == strategy) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5984 |                 (NUM_STRATEGIES == strategy)) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 5985 |                 isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5986 |             return true; | 
 | 5987 |         } | 
 | 5988 |     } | 
 | 5989 |     return false; | 
 | 5990 | } | 
 | 5991 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5992 | bool AudioPolicyManager::AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5993 |                                                                        uint32_t inPastMs, | 
 | 5994 |                                                                        nsecs_t sysTime) const | 
 | 5995 | { | 
 | 5996 |     if (mRefCount[stream] != 0) { | 
 | 5997 |         return true; | 
 | 5998 |     } | 
 | 5999 |     if (inPastMs == 0) { | 
 | 6000 |         return false; | 
 | 6001 |     } | 
 | 6002 |     if (sysTime == 0) { | 
 | 6003 |         sysTime = systemTime(); | 
 | 6004 |     } | 
 | 6005 |     if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { | 
 | 6006 |         return true; | 
 | 6007 |     } | 
 | 6008 |     return false; | 
 | 6009 | } | 
 | 6010 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6011 | void AudioPolicyManager::AudioOutputDescriptor::toAudioPortConfig( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6012 |                                                  struct audio_port_config *dstConfig, | 
 | 6013 |                                                  const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6014 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6015 |     ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); | 
 | 6016 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6017 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| | 
 | 6018 |                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; | 
 | 6019 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6020 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6021 |     } | 
 | 6022 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 6023 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6024 |     dstConfig->id = mId; | 
 | 6025 |     dstConfig->role = AUDIO_PORT_ROLE_SOURCE; | 
 | 6026 |     dstConfig->type = AUDIO_PORT_TYPE_MIX; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6027 |     dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; | 
 | 6028 |     dstConfig->ext.mix.handle = mIoHandle; | 
 | 6029 |     dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6030 | } | 
 | 6031 |  | 
 | 6032 | void AudioPolicyManager::AudioOutputDescriptor::toAudioPort( | 
 | 6033 |                                                     struct audio_port *port) const | 
 | 6034 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6035 |     ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6036 |     mProfile->toAudioPort(port); | 
 | 6037 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6038 |     toAudioPortConfig(&port->active_config); | 
 | 6039 |     port->ext.mix.hw_module = mProfile->mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6040 |     port->ext.mix.handle = mIoHandle; | 
 | 6041 |     port->ext.mix.latency_class = | 
 | 6042 |             mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; | 
 | 6043 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6044 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6045 | status_t AudioPolicyManager::AudioOutputDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6046 | { | 
 | 6047 |     const size_t SIZE = 256; | 
 | 6048 |     char buffer[SIZE]; | 
 | 6049 |     String8 result; | 
 | 6050 |  | 
| Eric Laurent | 4d41695 | 2014-08-10 14:07:09 -0700 | [diff] [blame] | 6051 |     snprintf(buffer, SIZE, " ID: %d\n", mId); | 
 | 6052 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6053 |     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); | 
 | 6054 |     result.append(buffer); | 
 | 6055 |     snprintf(buffer, SIZE, " Format: %08x\n", mFormat); | 
 | 6056 |     result.append(buffer); | 
 | 6057 |     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); | 
 | 6058 |     result.append(buffer); | 
 | 6059 |     snprintf(buffer, SIZE, " Latency: %d\n", mLatency); | 
 | 6060 |     result.append(buffer); | 
 | 6061 |     snprintf(buffer, SIZE, " Flags %08x\n", mFlags); | 
 | 6062 |     result.append(buffer); | 
 | 6063 |     snprintf(buffer, SIZE, " Devices %08x\n", device()); | 
 | 6064 |     result.append(buffer); | 
 | 6065 |     snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); | 
 | 6066 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 6067 |     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { | 
 | 6068 |         snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n", | 
 | 6069 |                  i, mCurVolume[i], mRefCount[i], mMuteCount[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6070 |         result.append(buffer); | 
 | 6071 |     } | 
 | 6072 |     write(fd, result.string(), result.size()); | 
 | 6073 |  | 
 | 6074 |     return NO_ERROR; | 
 | 6075 | } | 
 | 6076 |  | 
 | 6077 | // --- AudioInputDescriptor class implementation | 
 | 6078 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6079 | AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6080 |     : mId(0), mIoHandle(0), | 
| Eric Laurent | c722f30 | 2014-12-10 11:21:49 -0800 | [diff] [blame] | 6081 |       mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0), mRefCount(0), | 
| Eric Laurent | df3dc7e | 2014-07-27 18:39:40 -0700 | [diff] [blame] | 6082 |       mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6083 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6084 |     if (profile != NULL) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6085 |         mSamplingRate = profile->pickSamplingRate(); | 
 | 6086 |         mFormat = profile->pickFormat(); | 
 | 6087 |         mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6088 |         if (profile->mGains.size() > 0) { | 
 | 6089 |             profile->mGains[0]->getDefaultConfig(&mGain); | 
 | 6090 |         } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6091 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6092 | } | 
 | 6093 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6094 | void AudioPolicyManager::AudioInputDescriptor::toAudioPortConfig( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6095 |                                                    struct audio_port_config *dstConfig, | 
 | 6096 |                                                    const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6097 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6098 |     ALOG_ASSERT(mProfile != 0, | 
 | 6099 |                 "toAudioPortConfig() called on input with null profile %d", mIoHandle); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6100 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| | 
 | 6101 |                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; | 
 | 6102 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6103 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6104 |     } | 
 | 6105 |  | 
 | 6106 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 6107 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6108 |     dstConfig->id = mId; | 
 | 6109 |     dstConfig->role = AUDIO_PORT_ROLE_SINK; | 
 | 6110 |     dstConfig->type = AUDIO_PORT_TYPE_MIX; | 
| Eric Laurent | 62aaabb | 2014-06-02 10:40:54 -0700 | [diff] [blame] | 6111 |     dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; | 
 | 6112 |     dstConfig->ext.mix.handle = mIoHandle; | 
 | 6113 |     dstConfig->ext.mix.usecase.source = mInputSource; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6114 | } | 
 | 6115 |  | 
 | 6116 | void AudioPolicyManager::AudioInputDescriptor::toAudioPort( | 
 | 6117 |                                                     struct audio_port *port) const | 
 | 6118 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6119 |     ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle); | 
 | 6120 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6121 |     mProfile->toAudioPort(port); | 
 | 6122 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6123 |     toAudioPortConfig(&port->active_config); | 
 | 6124 |     port->ext.mix.hw_module = mProfile->mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6125 |     port->ext.mix.handle = mIoHandle; | 
 | 6126 |     port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL; | 
 | 6127 | } | 
 | 6128 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6129 | status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6130 | { | 
 | 6131 |     const size_t SIZE = 256; | 
 | 6132 |     char buffer[SIZE]; | 
 | 6133 |     String8 result; | 
 | 6134 |  | 
| Eric Laurent | 4d41695 | 2014-08-10 14:07:09 -0700 | [diff] [blame] | 6135 |     snprintf(buffer, SIZE, " ID: %d\n", mId); | 
 | 6136 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6137 |     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); | 
 | 6138 |     result.append(buffer); | 
 | 6139 |     snprintf(buffer, SIZE, " Format: %d\n", mFormat); | 
 | 6140 |     result.append(buffer); | 
 | 6141 |     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); | 
 | 6142 |     result.append(buffer); | 
 | 6143 |     snprintf(buffer, SIZE, " Devices %08x\n", mDevice); | 
 | 6144 |     result.append(buffer); | 
 | 6145 |     snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount); | 
 | 6146 |     result.append(buffer); | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 6147 |     snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount); | 
 | 6148 |     result.append(buffer); | 
 | 6149 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6150 |     write(fd, result.string(), result.size()); | 
 | 6151 |  | 
 | 6152 |     return NO_ERROR; | 
 | 6153 | } | 
 | 6154 |  | 
 | 6155 | // --- StreamDescriptor class implementation | 
 | 6156 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6157 | AudioPolicyManager::StreamDescriptor::StreamDescriptor() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6158 |     :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true) | 
 | 6159 | { | 
 | 6160 |     mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0); | 
 | 6161 | } | 
 | 6162 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6163 | int AudioPolicyManager::StreamDescriptor::getVolumeIndex(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6164 | { | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6165 |     device = AudioPolicyManager::getDeviceForVolume(device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6166 |     // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT | 
 | 6167 |     if (mIndexCur.indexOfKey(device) < 0) { | 
 | 6168 |         device = AUDIO_DEVICE_OUT_DEFAULT; | 
 | 6169 |     } | 
 | 6170 |     return mIndexCur.valueFor(device); | 
 | 6171 | } | 
 | 6172 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6173 | void AudioPolicyManager::StreamDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6174 | { | 
 | 6175 |     const size_t SIZE = 256; | 
 | 6176 |     char buffer[SIZE]; | 
 | 6177 |     String8 result; | 
 | 6178 |  | 
 | 6179 |     snprintf(buffer, SIZE, "%s         %02d         %02d         ", | 
 | 6180 |              mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax); | 
 | 6181 |     result.append(buffer); | 
 | 6182 |     for (size_t i = 0; i < mIndexCur.size(); i++) { | 
 | 6183 |         snprintf(buffer, SIZE, "%04x : %02d, ", | 
 | 6184 |                  mIndexCur.keyAt(i), | 
 | 6185 |                  mIndexCur.valueAt(i)); | 
 | 6186 |         result.append(buffer); | 
 | 6187 |     } | 
 | 6188 |     result.append("\n"); | 
 | 6189 |  | 
 | 6190 |     write(fd, result.string(), result.size()); | 
 | 6191 | } | 
 | 6192 |  | 
 | 6193 | // --- EffectDescriptor class implementation | 
 | 6194 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6195 | status_t AudioPolicyManager::EffectDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6196 | { | 
 | 6197 |     const size_t SIZE = 256; | 
 | 6198 |     char buffer[SIZE]; | 
 | 6199 |     String8 result; | 
 | 6200 |  | 
 | 6201 |     snprintf(buffer, SIZE, " I/O: %d\n", mIo); | 
 | 6202 |     result.append(buffer); | 
 | 6203 |     snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy); | 
 | 6204 |     result.append(buffer); | 
 | 6205 |     snprintf(buffer, SIZE, " Session: %d\n", mSession); | 
 | 6206 |     result.append(buffer); | 
 | 6207 |     snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name); | 
 | 6208 |     result.append(buffer); | 
 | 6209 |     snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled"); | 
 | 6210 |     result.append(buffer); | 
 | 6211 |     write(fd, result.string(), result.size()); | 
 | 6212 |  | 
 | 6213 |     return NO_ERROR; | 
 | 6214 | } | 
 | 6215 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6216 | // --- HwModule class implementation | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6217 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6218 | AudioPolicyManager::HwModule::HwModule(const char *name) | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 6219 |     : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)), | 
 | 6220 |       mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6221 | { | 
 | 6222 | } | 
 | 6223 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6224 | AudioPolicyManager::HwModule::~HwModule() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6225 | { | 
 | 6226 |     for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6227 |         mOutputProfiles[i]->mSupportedDevices.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6228 |     } | 
 | 6229 |     for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6230 |         mInputProfiles[i]->mSupportedDevices.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6231 |     } | 
 | 6232 |     free((void *)mName); | 
 | 6233 | } | 
 | 6234 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6235 | status_t AudioPolicyManager::HwModule::loadInput(cnode *root) | 
 | 6236 | { | 
 | 6237 |     cnode *node = root->first_child; | 
 | 6238 |  | 
 | 6239 |     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this); | 
 | 6240 |  | 
 | 6241 |     while (node) { | 
 | 6242 |         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { | 
 | 6243 |             profile->loadSamplingRates((char *)node->value); | 
 | 6244 |         } else if (strcmp(node->name, FORMATS_TAG) == 0) { | 
 | 6245 |             profile->loadFormats((char *)node->value); | 
 | 6246 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 6247 |             profile->loadInChannels((char *)node->value); | 
 | 6248 |         } else if (strcmp(node->name, DEVICES_TAG) == 0) { | 
 | 6249 |             profile->mSupportedDevices.loadDevicesFromName((char *)node->value, | 
 | 6250 |                                                            mDeclaredDevices); | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 6251 |         } else if (strcmp(node->name, FLAGS_TAG) == 0) { | 
 | 6252 |             profile->mFlags = parseInputFlagNames((char *)node->value); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6253 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 6254 |             profile->loadGains(node); | 
 | 6255 |         } | 
 | 6256 |         node = node->next; | 
 | 6257 |     } | 
 | 6258 |     ALOGW_IF(profile->mSupportedDevices.isEmpty(), | 
 | 6259 |             "loadInput() invalid supported devices"); | 
 | 6260 |     ALOGW_IF(profile->mChannelMasks.size() == 0, | 
 | 6261 |             "loadInput() invalid supported channel masks"); | 
 | 6262 |     ALOGW_IF(profile->mSamplingRates.size() == 0, | 
 | 6263 |             "loadInput() invalid supported sampling rates"); | 
 | 6264 |     ALOGW_IF(profile->mFormats.size() == 0, | 
 | 6265 |             "loadInput() invalid supported formats"); | 
 | 6266 |     if (!profile->mSupportedDevices.isEmpty() && | 
 | 6267 |             (profile->mChannelMasks.size() != 0) && | 
 | 6268 |             (profile->mSamplingRates.size() != 0) && | 
 | 6269 |             (profile->mFormats.size() != 0)) { | 
 | 6270 |  | 
 | 6271 |         ALOGV("loadInput() adding input Supported Devices %04x", | 
 | 6272 |               profile->mSupportedDevices.types()); | 
 | 6273 |  | 
 | 6274 |         mInputProfiles.add(profile); | 
 | 6275 |         return NO_ERROR; | 
 | 6276 |     } else { | 
 | 6277 |         return BAD_VALUE; | 
 | 6278 |     } | 
 | 6279 | } | 
 | 6280 |  | 
 | 6281 | status_t AudioPolicyManager::HwModule::loadOutput(cnode *root) | 
 | 6282 | { | 
 | 6283 |     cnode *node = root->first_child; | 
 | 6284 |  | 
 | 6285 |     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this); | 
 | 6286 |  | 
 | 6287 |     while (node) { | 
 | 6288 |         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { | 
 | 6289 |             profile->loadSamplingRates((char *)node->value); | 
 | 6290 |         } else if (strcmp(node->name, FORMATS_TAG) == 0) { | 
 | 6291 |             profile->loadFormats((char *)node->value); | 
 | 6292 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 6293 |             profile->loadOutChannels((char *)node->value); | 
 | 6294 |         } else if (strcmp(node->name, DEVICES_TAG) == 0) { | 
 | 6295 |             profile->mSupportedDevices.loadDevicesFromName((char *)node->value, | 
 | 6296 |                                                            mDeclaredDevices); | 
 | 6297 |         } else if (strcmp(node->name, FLAGS_TAG) == 0) { | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 6298 |             profile->mFlags = parseOutputFlagNames((char *)node->value); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6299 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 6300 |             profile->loadGains(node); | 
 | 6301 |         } | 
 | 6302 |         node = node->next; | 
 | 6303 |     } | 
 | 6304 |     ALOGW_IF(profile->mSupportedDevices.isEmpty(), | 
 | 6305 |             "loadOutput() invalid supported devices"); | 
 | 6306 |     ALOGW_IF(profile->mChannelMasks.size() == 0, | 
 | 6307 |             "loadOutput() invalid supported channel masks"); | 
 | 6308 |     ALOGW_IF(profile->mSamplingRates.size() == 0, | 
 | 6309 |             "loadOutput() invalid supported sampling rates"); | 
 | 6310 |     ALOGW_IF(profile->mFormats.size() == 0, | 
 | 6311 |             "loadOutput() invalid supported formats"); | 
 | 6312 |     if (!profile->mSupportedDevices.isEmpty() && | 
 | 6313 |             (profile->mChannelMasks.size() != 0) && | 
 | 6314 |             (profile->mSamplingRates.size() != 0) && | 
 | 6315 |             (profile->mFormats.size() != 0)) { | 
 | 6316 |  | 
 | 6317 |         ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x", | 
 | 6318 |               profile->mSupportedDevices.types(), profile->mFlags); | 
 | 6319 |  | 
 | 6320 |         mOutputProfiles.add(profile); | 
 | 6321 |         return NO_ERROR; | 
 | 6322 |     } else { | 
 | 6323 |         return BAD_VALUE; | 
 | 6324 |     } | 
 | 6325 | } | 
 | 6326 |  | 
 | 6327 | status_t AudioPolicyManager::HwModule::loadDevice(cnode *root) | 
 | 6328 | { | 
 | 6329 |     cnode *node = root->first_child; | 
 | 6330 |  | 
 | 6331 |     audio_devices_t type = AUDIO_DEVICE_NONE; | 
 | 6332 |     while (node) { | 
 | 6333 |         if (strcmp(node->name, DEVICE_TYPE) == 0) { | 
 | 6334 |             type = parseDeviceNames((char *)node->value); | 
 | 6335 |             break; | 
 | 6336 |         } | 
 | 6337 |         node = node->next; | 
 | 6338 |     } | 
 | 6339 |     if (type == AUDIO_DEVICE_NONE || | 
 | 6340 |             (!audio_is_input_device(type) && !audio_is_output_device(type))) { | 
 | 6341 |         ALOGW("loadDevice() bad type %08x", type); | 
 | 6342 |         return BAD_VALUE; | 
 | 6343 |     } | 
 | 6344 |     sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type); | 
 | 6345 |     deviceDesc->mModule = this; | 
 | 6346 |  | 
 | 6347 |     node = root->first_child; | 
 | 6348 |     while (node) { | 
 | 6349 |         if (strcmp(node->name, DEVICE_ADDRESS) == 0) { | 
 | 6350 |             deviceDesc->mAddress = String8((char *)node->value); | 
 | 6351 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 6352 |             if (audio_is_input_device(type)) { | 
 | 6353 |                 deviceDesc->loadInChannels((char *)node->value); | 
 | 6354 |             } else { | 
 | 6355 |                 deviceDesc->loadOutChannels((char *)node->value); | 
 | 6356 |             } | 
 | 6357 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 6358 |             deviceDesc->loadGains(node); | 
 | 6359 |         } | 
 | 6360 |         node = node->next; | 
 | 6361 |     } | 
 | 6362 |  | 
 | 6363 |     ALOGV("loadDevice() adding device name %s type %08x address %s", | 
 | 6364 |           deviceDesc->mName.string(), type, deviceDesc->mAddress.string()); | 
 | 6365 |  | 
 | 6366 |     mDeclaredDevices.add(deviceDesc); | 
 | 6367 |  | 
 | 6368 |     return NO_ERROR; | 
 | 6369 | } | 
 | 6370 |  | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 6371 | status_t AudioPolicyManager::HwModule::addOutputProfile(String8 name, const audio_config_t *config, | 
 | 6372 |                                                   audio_devices_t device, String8 address) | 
 | 6373 | { | 
 | 6374 |     sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE, this); | 
 | 6375 |  | 
 | 6376 |     profile->mSamplingRates.add(config->sample_rate); | 
 | 6377 |     profile->mChannelMasks.add(config->channel_mask); | 
 | 6378 |     profile->mFormats.add(config->format); | 
 | 6379 |  | 
 | 6380 |     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 6381 |     devDesc->mAddress = address; | 
 | 6382 |     profile->mSupportedDevices.add(devDesc); | 
 | 6383 |  | 
 | 6384 |     mOutputProfiles.add(profile); | 
 | 6385 |  | 
 | 6386 |     return NO_ERROR; | 
 | 6387 | } | 
 | 6388 |  | 
 | 6389 | status_t AudioPolicyManager::HwModule::removeOutputProfile(String8 name) | 
 | 6390 | { | 
 | 6391 |     for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
 | 6392 |         if (mOutputProfiles[i]->mName == name) { | 
 | 6393 |             mOutputProfiles.removeAt(i); | 
 | 6394 |             break; | 
 | 6395 |         } | 
 | 6396 |     } | 
 | 6397 |  | 
 | 6398 |     return NO_ERROR; | 
 | 6399 | } | 
 | 6400 |  | 
 | 6401 | status_t AudioPolicyManager::HwModule::addInputProfile(String8 name, const audio_config_t *config, | 
 | 6402 |                                                   audio_devices_t device, String8 address) | 
 | 6403 | { | 
 | 6404 |     sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK, this); | 
 | 6405 |  | 
 | 6406 |     profile->mSamplingRates.add(config->sample_rate); | 
 | 6407 |     profile->mChannelMasks.add(config->channel_mask); | 
 | 6408 |     profile->mFormats.add(config->format); | 
 | 6409 |  | 
 | 6410 |     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 6411 |     devDesc->mAddress = address; | 
 | 6412 |     profile->mSupportedDevices.add(devDesc); | 
 | 6413 |  | 
 | 6414 |     ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask); | 
 | 6415 |  | 
 | 6416 |     mInputProfiles.add(profile); | 
 | 6417 |  | 
 | 6418 |     return NO_ERROR; | 
 | 6419 | } | 
 | 6420 |  | 
 | 6421 | status_t AudioPolicyManager::HwModule::removeInputProfile(String8 name) | 
 | 6422 | { | 
 | 6423 |     for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
 | 6424 |         if (mInputProfiles[i]->mName == name) { | 
 | 6425 |             mInputProfiles.removeAt(i); | 
 | 6426 |             break; | 
 | 6427 |         } | 
 | 6428 |     } | 
 | 6429 |  | 
 | 6430 |     return NO_ERROR; | 
 | 6431 | } | 
 | 6432 |  | 
 | 6433 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6434 | void AudioPolicyManager::HwModule::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6435 | { | 
 | 6436 |     const size_t SIZE = 256; | 
 | 6437 |     char buffer[SIZE]; | 
 | 6438 |     String8 result; | 
 | 6439 |  | 
 | 6440 |     snprintf(buffer, SIZE, "  - name: %s\n", mName); | 
 | 6441 |     result.append(buffer); | 
 | 6442 |     snprintf(buffer, SIZE, "  - handle: %d\n", mHandle); | 
 | 6443 |     result.append(buffer); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 6444 |     snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF); | 
 | 6445 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6446 |     write(fd, result.string(), result.size()); | 
 | 6447 |     if (mOutputProfiles.size()) { | 
 | 6448 |         write(fd, "  - outputs:\n", strlen("  - outputs:\n")); | 
 | 6449 |         for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 6450 |             snprintf(buffer, SIZE, "    output %zu:\n", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6451 |             write(fd, buffer, strlen(buffer)); | 
 | 6452 |             mOutputProfiles[i]->dump(fd); | 
 | 6453 |         } | 
 | 6454 |     } | 
 | 6455 |     if (mInputProfiles.size()) { | 
 | 6456 |         write(fd, "  - inputs:\n", strlen("  - inputs:\n")); | 
 | 6457 |         for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 6458 |             snprintf(buffer, SIZE, "    input %zu:\n", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6459 |             write(fd, buffer, strlen(buffer)); | 
 | 6460 |             mInputProfiles[i]->dump(fd); | 
 | 6461 |         } | 
 | 6462 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6463 |     if (mDeclaredDevices.size()) { | 
 | 6464 |         write(fd, "  - devices:\n", strlen("  - devices:\n")); | 
 | 6465 |         for (size_t i = 0; i < mDeclaredDevices.size(); i++) { | 
 | 6466 |             mDeclaredDevices[i]->dump(fd, 4, i); | 
 | 6467 |         } | 
 | 6468 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6469 | } | 
 | 6470 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6471 | // --- AudioPort class implementation | 
 | 6472 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6473 |  | 
 | 6474 | AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type, | 
 | 6475 |           audio_port_role_t role, const sp<HwModule>& module) : | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 6476 |     mName(name), mType(type), mRole(role), mModule(module), mFlags(0) | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6477 | { | 
 | 6478 |     mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || | 
 | 6479 |                     ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); | 
 | 6480 | } | 
 | 6481 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6482 | void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const | 
 | 6483 | { | 
 | 6484 |     port->role = mRole; | 
 | 6485 |     port->type = mType; | 
 | 6486 |     unsigned int i; | 
 | 6487 |     for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) { | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 6488 |         if (mSamplingRates[i] != 0) { | 
 | 6489 |             port->sample_rates[i] = mSamplingRates[i]; | 
 | 6490 |         } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6491 |     } | 
 | 6492 |     port->num_sample_rates = i; | 
 | 6493 |     for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) { | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 6494 |         if (mChannelMasks[i] != 0) { | 
 | 6495 |             port->channel_masks[i] = mChannelMasks[i]; | 
 | 6496 |         } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6497 |     } | 
 | 6498 |     port->num_channel_masks = i; | 
 | 6499 |     for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) { | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 6500 |         if (mFormats[i] != 0) { | 
 | 6501 |             port->formats[i] = mFormats[i]; | 
 | 6502 |         } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6503 |     } | 
 | 6504 |     port->num_formats = i; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 6505 |  | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 6506 |     ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 6507 |  | 
 | 6508 |     for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { | 
 | 6509 |         port->gains[i] = mGains[i]->mGain; | 
 | 6510 |     } | 
 | 6511 |     port->num_gains = i; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6512 | } | 
 | 6513 |  | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 6514 | void AudioPolicyManager::AudioPort::importAudioPort(const sp<AudioPort> port) { | 
 | 6515 |     for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) { | 
 | 6516 |         const uint32_t rate = port->mSamplingRates.itemAt(k); | 
 | 6517 |         if (rate != 0) { // skip "dynamic" rates | 
 | 6518 |             bool hasRate = false; | 
 | 6519 |             for (size_t l = 0 ; l < mSamplingRates.size() ; l++) { | 
 | 6520 |                 if (rate == mSamplingRates.itemAt(l)) { | 
 | 6521 |                     hasRate = true; | 
 | 6522 |                     break; | 
 | 6523 |                 } | 
 | 6524 |             } | 
 | 6525 |             if (!hasRate) { // never import a sampling rate twice | 
 | 6526 |                 mSamplingRates.add(rate); | 
 | 6527 |             } | 
 | 6528 |         } | 
 | 6529 |     } | 
 | 6530 |     for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) { | 
 | 6531 |         const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k); | 
 | 6532 |         if (mask != 0) { // skip "dynamic" masks | 
 | 6533 |             bool hasMask = false; | 
 | 6534 |             for (size_t l = 0 ; l < mChannelMasks.size() ; l++) { | 
 | 6535 |                 if (mask == mChannelMasks.itemAt(l)) { | 
 | 6536 |                     hasMask = true; | 
 | 6537 |                     break; | 
 | 6538 |                 } | 
 | 6539 |             } | 
 | 6540 |             if (!hasMask) { // never import a channel mask twice | 
 | 6541 |                 mChannelMasks.add(mask); | 
 | 6542 |             } | 
 | 6543 |         } | 
 | 6544 |     } | 
 | 6545 |     for (size_t k = 0 ; k < port->mFormats.size() ; k++) { | 
 | 6546 |         const audio_format_t format = port->mFormats.itemAt(k); | 
 | 6547 |         if (format != 0) { // skip "dynamic" formats | 
 | 6548 |             bool hasFormat = false; | 
 | 6549 |             for (size_t l = 0 ; l < mFormats.size() ; l++) { | 
 | 6550 |                 if (format == mFormats.itemAt(l)) { | 
 | 6551 |                     hasFormat = true; | 
 | 6552 |                     break; | 
 | 6553 |                 } | 
 | 6554 |             } | 
 | 6555 |             if (!hasFormat) { // never import a channel mask twice | 
 | 6556 |                 mFormats.add(format); | 
 | 6557 |             } | 
 | 6558 |         } | 
 | 6559 |     } | 
| Hochi Huang | 23fe3c0 | 2014-10-03 09:09:30 +0800 | [diff] [blame] | 6560 |     for (size_t k = 0 ; k < port->mGains.size() ; k++) { | 
 | 6561 |         sp<AudioGain> gain = port->mGains.itemAt(k); | 
 | 6562 |         if (gain != 0) { | 
 | 6563 |             bool hasGain = false; | 
 | 6564 |             for (size_t l = 0 ; l < mGains.size() ; l++) { | 
 | 6565 |                 if (gain == mGains.itemAt(l)) { | 
 | 6566 |                     hasGain = true; | 
 | 6567 |                     break; | 
 | 6568 |                 } | 
 | 6569 |             } | 
 | 6570 |             if (!hasGain) { // never import a gain twice | 
 | 6571 |                 mGains.add(gain); | 
 | 6572 |             } | 
 | 6573 |         } | 
 | 6574 |     } | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 6575 | } | 
 | 6576 |  | 
 | 6577 | void AudioPolicyManager::AudioPort::clearCapabilities() { | 
 | 6578 |     mChannelMasks.clear(); | 
 | 6579 |     mFormats.clear(); | 
 | 6580 |     mSamplingRates.clear(); | 
| Hochi Huang | 23fe3c0 | 2014-10-03 09:09:30 +0800 | [diff] [blame] | 6581 |     mGains.clear(); | 
| Jean-Michel Trivi | f17026d | 2014-08-10 14:30:48 -0700 | [diff] [blame] | 6582 | } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6583 |  | 
 | 6584 | void AudioPolicyManager::AudioPort::loadSamplingRates(char *name) | 
 | 6585 | { | 
 | 6586 |     char *str = strtok(name, "|"); | 
 | 6587 |  | 
 | 6588 |     // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling | 
 | 6589 |     // rates should be read from the output stream after it is opened for the first time | 
 | 6590 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 6591 |         mSamplingRates.add(0); | 
 | 6592 |         return; | 
 | 6593 |     } | 
 | 6594 |  | 
 | 6595 |     while (str != NULL) { | 
 | 6596 |         uint32_t rate = atoi(str); | 
 | 6597 |         if (rate != 0) { | 
 | 6598 |             ALOGV("loadSamplingRates() adding rate %d", rate); | 
 | 6599 |             mSamplingRates.add(rate); | 
 | 6600 |         } | 
 | 6601 |         str = strtok(NULL, "|"); | 
 | 6602 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6603 | } | 
 | 6604 |  | 
 | 6605 | void AudioPolicyManager::AudioPort::loadFormats(char *name) | 
 | 6606 | { | 
 | 6607 |     char *str = strtok(name, "|"); | 
 | 6608 |  | 
 | 6609 |     // by convention, "0' in the first entry in mFormats indicates the supported formats | 
 | 6610 |     // should be read from the output stream after it is opened for the first time | 
 | 6611 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 6612 |         mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 6613 |         return; | 
 | 6614 |     } | 
 | 6615 |  | 
 | 6616 |     while (str != NULL) { | 
 | 6617 |         audio_format_t format = (audio_format_t)stringToEnum(sFormatNameToEnumTable, | 
 | 6618 |                                                              ARRAY_SIZE(sFormatNameToEnumTable), | 
 | 6619 |                                                              str); | 
 | 6620 |         if (format != AUDIO_FORMAT_DEFAULT) { | 
 | 6621 |             mFormats.add(format); | 
 | 6622 |         } | 
 | 6623 |         str = strtok(NULL, "|"); | 
 | 6624 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6625 | } | 
 | 6626 |  | 
 | 6627 | void AudioPolicyManager::AudioPort::loadInChannels(char *name) | 
 | 6628 | { | 
 | 6629 |     const char *str = strtok(name, "|"); | 
 | 6630 |  | 
 | 6631 |     ALOGV("loadInChannels() %s", name); | 
 | 6632 |  | 
 | 6633 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 6634 |         mChannelMasks.add(0); | 
 | 6635 |         return; | 
 | 6636 |     } | 
 | 6637 |  | 
 | 6638 |     while (str != NULL) { | 
 | 6639 |         audio_channel_mask_t channelMask = | 
 | 6640 |                 (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, | 
 | 6641 |                                                    ARRAY_SIZE(sInChannelsNameToEnumTable), | 
 | 6642 |                                                    str); | 
 | 6643 |         if (channelMask != 0) { | 
 | 6644 |             ALOGV("loadInChannels() adding channelMask %04x", channelMask); | 
 | 6645 |             mChannelMasks.add(channelMask); | 
 | 6646 |         } | 
 | 6647 |         str = strtok(NULL, "|"); | 
 | 6648 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6649 | } | 
 | 6650 |  | 
 | 6651 | void AudioPolicyManager::AudioPort::loadOutChannels(char *name) | 
 | 6652 | { | 
 | 6653 |     const char *str = strtok(name, "|"); | 
 | 6654 |  | 
 | 6655 |     ALOGV("loadOutChannels() %s", name); | 
 | 6656 |  | 
 | 6657 |     // by convention, "0' in the first entry in mChannelMasks indicates the supported channel | 
 | 6658 |     // masks should be read from the output stream after it is opened for the first time | 
 | 6659 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 6660 |         mChannelMasks.add(0); | 
 | 6661 |         return; | 
 | 6662 |     } | 
 | 6663 |  | 
 | 6664 |     while (str != NULL) { | 
 | 6665 |         audio_channel_mask_t channelMask = | 
 | 6666 |                 (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, | 
 | 6667 |                                                    ARRAY_SIZE(sOutChannelsNameToEnumTable), | 
 | 6668 |                                                    str); | 
 | 6669 |         if (channelMask != 0) { | 
 | 6670 |             mChannelMasks.add(channelMask); | 
 | 6671 |         } | 
 | 6672 |         str = strtok(NULL, "|"); | 
 | 6673 |     } | 
 | 6674 |     return; | 
 | 6675 | } | 
 | 6676 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6677 | audio_gain_mode_t AudioPolicyManager::AudioPort::loadGainMode(char *name) | 
 | 6678 | { | 
 | 6679 |     const char *str = strtok(name, "|"); | 
 | 6680 |  | 
 | 6681 |     ALOGV("loadGainMode() %s", name); | 
 | 6682 |     audio_gain_mode_t mode = 0; | 
 | 6683 |     while (str != NULL) { | 
 | 6684 |         mode |= (audio_gain_mode_t)stringToEnum(sGainModeNameToEnumTable, | 
 | 6685 |                                                 ARRAY_SIZE(sGainModeNameToEnumTable), | 
 | 6686 |                                                 str); | 
 | 6687 |         str = strtok(NULL, "|"); | 
 | 6688 |     } | 
 | 6689 |     return mode; | 
 | 6690 | } | 
 | 6691 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6692 | void AudioPolicyManager::AudioPort::loadGain(cnode *root, int index) | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6693 | { | 
 | 6694 |     cnode *node = root->first_child; | 
 | 6695 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6696 |     sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6697 |  | 
 | 6698 |     while (node) { | 
 | 6699 |         if (strcmp(node->name, GAIN_MODE) == 0) { | 
 | 6700 |             gain->mGain.mode = loadGainMode((char *)node->value); | 
 | 6701 |         } else if (strcmp(node->name, GAIN_CHANNELS) == 0) { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6702 |             if (mUseInChannelMask) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6703 |                 gain->mGain.channel_mask = | 
 | 6704 |                         (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, | 
 | 6705 |                                                            ARRAY_SIZE(sInChannelsNameToEnumTable), | 
 | 6706 |                                                            (char *)node->value); | 
 | 6707 |             } else { | 
 | 6708 |                 gain->mGain.channel_mask = | 
 | 6709 |                         (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, | 
 | 6710 |                                                            ARRAY_SIZE(sOutChannelsNameToEnumTable), | 
 | 6711 |                                                            (char *)node->value); | 
 | 6712 |             } | 
 | 6713 |         } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) { | 
 | 6714 |             gain->mGain.min_value = atoi((char *)node->value); | 
 | 6715 |         } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) { | 
 | 6716 |             gain->mGain.max_value = atoi((char *)node->value); | 
 | 6717 |         } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) { | 
 | 6718 |             gain->mGain.default_value = atoi((char *)node->value); | 
 | 6719 |         } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) { | 
 | 6720 |             gain->mGain.step_value = atoi((char *)node->value); | 
 | 6721 |         } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) { | 
 | 6722 |             gain->mGain.min_ramp_ms = atoi((char *)node->value); | 
 | 6723 |         } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) { | 
 | 6724 |             gain->mGain.max_ramp_ms = atoi((char *)node->value); | 
 | 6725 |         } | 
 | 6726 |         node = node->next; | 
 | 6727 |     } | 
 | 6728 |  | 
 | 6729 |     ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d", | 
 | 6730 |           gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value); | 
 | 6731 |  | 
 | 6732 |     if (gain->mGain.mode == 0) { | 
 | 6733 |         return; | 
 | 6734 |     } | 
 | 6735 |     mGains.add(gain); | 
 | 6736 | } | 
 | 6737 |  | 
 | 6738 | void AudioPolicyManager::AudioPort::loadGains(cnode *root) | 
 | 6739 | { | 
 | 6740 |     cnode *node = root->first_child; | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6741 |     int index = 0; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6742 |     while (node) { | 
 | 6743 |         ALOGV("loadGains() loading gain %s", node->name); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6744 |         loadGain(node, index++); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6745 |         node = node->next; | 
 | 6746 |     } | 
 | 6747 | } | 
 | 6748 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 6749 | status_t AudioPolicyManager::AudioPort::checkExactSamplingRate(uint32_t samplingRate) const | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6750 | { | 
| Eric Laurent | 0daea39 | 2014-12-04 19:14:54 -0800 | [diff] [blame] | 6751 |     if (mSamplingRates.isEmpty()) { | 
 | 6752 |         return NO_ERROR; | 
 | 6753 |     } | 
 | 6754 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6755 |     for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 6756 |         if (mSamplingRates[i] == samplingRate) { | 
 | 6757 |             return NO_ERROR; | 
 | 6758 |         } | 
 | 6759 |     } | 
 | 6760 |     return BAD_VALUE; | 
 | 6761 | } | 
 | 6762 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 6763 | status_t AudioPolicyManager::AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate, | 
 | 6764 |         uint32_t *updatedSamplingRate) const | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6765 | { | 
| Eric Laurent | 0daea39 | 2014-12-04 19:14:54 -0800 | [diff] [blame] | 6766 |     if (mSamplingRates.isEmpty()) { | 
 | 6767 |         return NO_ERROR; | 
 | 6768 |     } | 
 | 6769 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 6770 |     // Search for the closest supported sampling rate that is above (preferred) | 
 | 6771 |     // or below (acceptable) the desired sampling rate, within a permitted ratio. | 
 | 6772 |     // The sampling rates do not need to be sorted in ascending order. | 
 | 6773 |     ssize_t maxBelow = -1; | 
 | 6774 |     ssize_t minAbove = -1; | 
 | 6775 |     uint32_t candidate; | 
 | 6776 |     for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
 | 6777 |         candidate = mSamplingRates[i]; | 
 | 6778 |         if (candidate == samplingRate) { | 
 | 6779 |             if (updatedSamplingRate != NULL) { | 
 | 6780 |                 *updatedSamplingRate = candidate; | 
 | 6781 |             } | 
 | 6782 |             return NO_ERROR; | 
 | 6783 |         } | 
 | 6784 |         // candidate < desired | 
 | 6785 |         if (candidate < samplingRate) { | 
 | 6786 |             if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) { | 
 | 6787 |                 maxBelow = i; | 
 | 6788 |             } | 
 | 6789 |         // candidate > desired | 
 | 6790 |         } else { | 
 | 6791 |             if (minAbove < 0 || candidate < mSamplingRates[minAbove]) { | 
 | 6792 |                 minAbove = i; | 
 | 6793 |             } | 
 | 6794 |         } | 
 | 6795 |     } | 
 | 6796 |     // This uses hard-coded knowledge about AudioFlinger resampling ratios. | 
 | 6797 |     // TODO Move these assumptions out. | 
 | 6798 |     static const uint32_t kMaxDownSampleRatio = 6;  // beyond this aliasing occurs | 
 | 6799 |     static const uint32_t kMaxUpSampleRatio = 256;  // beyond this sample rate inaccuracies occur | 
 | 6800 |                                                     // due to approximation by an int32_t of the | 
 | 6801 |                                                     // phase increments | 
 | 6802 |     // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. | 
 | 6803 |     if (minAbove >= 0) { | 
 | 6804 |         candidate = mSamplingRates[minAbove]; | 
 | 6805 |         if (candidate / kMaxDownSampleRatio <= samplingRate) { | 
 | 6806 |             if (updatedSamplingRate != NULL) { | 
 | 6807 |                 *updatedSamplingRate = candidate; | 
 | 6808 |             } | 
 | 6809 |             return NO_ERROR; | 
 | 6810 |         } | 
 | 6811 |     } | 
 | 6812 |     // But if we have to up-sample from a lower sampling rate, that's OK. | 
 | 6813 |     if (maxBelow >= 0) { | 
 | 6814 |         candidate = mSamplingRates[maxBelow]; | 
 | 6815 |         if (candidate * kMaxUpSampleRatio >= samplingRate) { | 
 | 6816 |             if (updatedSamplingRate != NULL) { | 
 | 6817 |                 *updatedSamplingRate = candidate; | 
 | 6818 |             } | 
 | 6819 |             return NO_ERROR; | 
 | 6820 |         } | 
 | 6821 |     } | 
 | 6822 |     // leave updatedSamplingRate unmodified | 
 | 6823 |     return BAD_VALUE; | 
 | 6824 | } | 
 | 6825 |  | 
 | 6826 | status_t AudioPolicyManager::AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const | 
 | 6827 | { | 
| Eric Laurent | 0daea39 | 2014-12-04 19:14:54 -0800 | [diff] [blame] | 6828 |     if (mChannelMasks.isEmpty()) { | 
 | 6829 |         return NO_ERROR; | 
 | 6830 |     } | 
 | 6831 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 6832 |     for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6833 |         if (mChannelMasks[i] == channelMask) { | 
 | 6834 |             return NO_ERROR; | 
 | 6835 |         } | 
 | 6836 |     } | 
 | 6837 |     return BAD_VALUE; | 
 | 6838 | } | 
 | 6839 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 6840 | status_t AudioPolicyManager::AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask) | 
 | 6841 |         const | 
 | 6842 | { | 
| Eric Laurent | 0daea39 | 2014-12-04 19:14:54 -0800 | [diff] [blame] | 6843 |     if (mChannelMasks.isEmpty()) { | 
 | 6844 |         return NO_ERROR; | 
 | 6845 |     } | 
 | 6846 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 6847 |     const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; | 
 | 6848 |     for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 6849 |         // FIXME Does not handle multi-channel automatic conversions yet | 
 | 6850 |         audio_channel_mask_t supported = mChannelMasks[i]; | 
 | 6851 |         if (supported == channelMask) { | 
 | 6852 |             return NO_ERROR; | 
 | 6853 |         } | 
 | 6854 |         if (isRecordThread) { | 
 | 6855 |             // This uses hard-coded knowledge that AudioFlinger can silently down-mix and up-mix. | 
 | 6856 |             // FIXME Abstract this out to a table. | 
 | 6857 |             if (((supported == AUDIO_CHANNEL_IN_FRONT_BACK || supported == AUDIO_CHANNEL_IN_STEREO) | 
 | 6858 |                     && channelMask == AUDIO_CHANNEL_IN_MONO) || | 
 | 6859 |                 (supported == AUDIO_CHANNEL_IN_MONO && (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK | 
 | 6860 |                     || channelMask == AUDIO_CHANNEL_IN_STEREO))) { | 
 | 6861 |                 return NO_ERROR; | 
 | 6862 |             } | 
 | 6863 |         } | 
 | 6864 |     } | 
 | 6865 |     return BAD_VALUE; | 
 | 6866 | } | 
 | 6867 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6868 | status_t AudioPolicyManager::AudioPort::checkFormat(audio_format_t format) const | 
 | 6869 | { | 
| Eric Laurent | 0daea39 | 2014-12-04 19:14:54 -0800 | [diff] [blame] | 6870 |     if (mFormats.isEmpty()) { | 
 | 6871 |         return NO_ERROR; | 
 | 6872 |     } | 
 | 6873 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6874 |     for (size_t i = 0; i < mFormats.size(); i ++) { | 
 | 6875 |         if (mFormats[i] == format) { | 
 | 6876 |             return NO_ERROR; | 
 | 6877 |         } | 
 | 6878 |     } | 
 | 6879 |     return BAD_VALUE; | 
 | 6880 | } | 
 | 6881 |  | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6882 |  | 
 | 6883 | uint32_t AudioPolicyManager::AudioPort::pickSamplingRate() const | 
 | 6884 | { | 
 | 6885 |     // special case for uninitialized dynamic profile | 
 | 6886 |     if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) { | 
 | 6887 |         return 0; | 
 | 6888 |     } | 
 | 6889 |  | 
| Eric Laurent | 828bcff | 2014-09-07 12:26:06 -0700 | [diff] [blame] | 6890 |     // For direct outputs, pick minimum sampling rate: this helps ensuring that the | 
 | 6891 |     // channel count / sampling rate combination chosen will be supported by the connected | 
 | 6892 |     // sink | 
 | 6893 |     if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 6894 |             (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { | 
 | 6895 |         uint32_t samplingRate = UINT_MAX; | 
 | 6896 |         for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 6897 |             if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) { | 
 | 6898 |                 samplingRate = mSamplingRates[i]; | 
 | 6899 |             } | 
 | 6900 |         } | 
 | 6901 |         return (samplingRate == UINT_MAX) ? 0 : samplingRate; | 
 | 6902 |     } | 
 | 6903 |  | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6904 |     uint32_t samplingRate = 0; | 
 | 6905 |     uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; | 
 | 6906 |  | 
 | 6907 |     // For mixed output and inputs, use max mixer sampling rates. Do not | 
 | 6908 |     // limit sampling rate otherwise | 
| Eric Laurent | 828bcff | 2014-09-07 12:26:06 -0700 | [diff] [blame] | 6909 |     if (mType != AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6910 |         maxRate = UINT_MAX; | 
 | 6911 |     } | 
 | 6912 |     for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 6913 |         if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) { | 
 | 6914 |             samplingRate = mSamplingRates[i]; | 
 | 6915 |         } | 
 | 6916 |     } | 
 | 6917 |     return samplingRate; | 
 | 6918 | } | 
 | 6919 |  | 
 | 6920 | audio_channel_mask_t AudioPolicyManager::AudioPort::pickChannelMask() const | 
 | 6921 | { | 
 | 6922 |     // special case for uninitialized dynamic profile | 
 | 6923 |     if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) { | 
 | 6924 |         return AUDIO_CHANNEL_NONE; | 
 | 6925 |     } | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6926 |     audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE; | 
| Eric Laurent | 828bcff | 2014-09-07 12:26:06 -0700 | [diff] [blame] | 6927 |  | 
 | 6928 |     // For direct outputs, pick minimum channel count: this helps ensuring that the | 
 | 6929 |     // channel count / sampling rate combination chosen will be supported by the connected | 
 | 6930 |     // sink | 
 | 6931 |     if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 6932 |             (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) { | 
 | 6933 |         uint32_t channelCount = UINT_MAX; | 
 | 6934 |         for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 6935 |             uint32_t cnlCount; | 
 | 6936 |             if (mUseInChannelMask) { | 
 | 6937 |                 cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); | 
 | 6938 |             } else { | 
 | 6939 |                 cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); | 
 | 6940 |             } | 
 | 6941 |             if ((cnlCount < channelCount) && (cnlCount > 0)) { | 
 | 6942 |                 channelMask = mChannelMasks[i]; | 
 | 6943 |                 channelCount = cnlCount; | 
 | 6944 |             } | 
 | 6945 |         } | 
 | 6946 |         return channelMask; | 
 | 6947 |     } | 
 | 6948 |  | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6949 |     uint32_t channelCount = 0; | 
 | 6950 |     uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; | 
 | 6951 |  | 
 | 6952 |     // For mixed output and inputs, use max mixer channel count. Do not | 
 | 6953 |     // limit channel count otherwise | 
| Eric Laurent | 828bcff | 2014-09-07 12:26:06 -0700 | [diff] [blame] | 6954 |     if (mType != AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6955 |         maxCount = UINT_MAX; | 
 | 6956 |     } | 
 | 6957 |     for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 6958 |         uint32_t cnlCount; | 
 | 6959 |         if (mUseInChannelMask) { | 
 | 6960 |             cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); | 
 | 6961 |         } else { | 
 | 6962 |             cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); | 
 | 6963 |         } | 
 | 6964 |         if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { | 
 | 6965 |             channelMask = mChannelMasks[i]; | 
| Eric Laurent | 828bcff | 2014-09-07 12:26:06 -0700 | [diff] [blame] | 6966 |             channelCount = cnlCount; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6967 |         } | 
 | 6968 |     } | 
 | 6969 |     return channelMask; | 
 | 6970 | } | 
 | 6971 |  | 
| Andy Hung | 9a60538 | 2014-07-28 16:16:31 -0700 | [diff] [blame] | 6972 | /* format in order of increasing preference */ | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6973 | const audio_format_t AudioPolicyManager::AudioPort::sPcmFormatCompareTable[] = { | 
 | 6974 |         AUDIO_FORMAT_DEFAULT, | 
 | 6975 |         AUDIO_FORMAT_PCM_16_BIT, | 
| Eric Laurent | a204994 | 2014-07-21 17:49:25 -0700 | [diff] [blame] | 6976 |         AUDIO_FORMAT_PCM_8_24_BIT, | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6977 |         AUDIO_FORMAT_PCM_24_BIT_PACKED, | 
| Eric Laurent | a204994 | 2014-07-21 17:49:25 -0700 | [diff] [blame] | 6978 |         AUDIO_FORMAT_PCM_32_BIT, | 
| Andy Hung | 9a60538 | 2014-07-28 16:16:31 -0700 | [diff] [blame] | 6979 |         AUDIO_FORMAT_PCM_FLOAT, | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6980 | }; | 
 | 6981 |  | 
 | 6982 | int AudioPolicyManager::AudioPort::compareFormats(audio_format_t format1, | 
 | 6983 |                                                   audio_format_t format2) | 
 | 6984 | { | 
 | 6985 |     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any | 
 | 6986 |     // compressed format and better than any PCM format. This is by design of pickFormat() | 
 | 6987 |     if (!audio_is_linear_pcm(format1)) { | 
 | 6988 |         if (!audio_is_linear_pcm(format2)) { | 
 | 6989 |             return 0; | 
 | 6990 |         } | 
 | 6991 |         return 1; | 
 | 6992 |     } | 
 | 6993 |     if (!audio_is_linear_pcm(format2)) { | 
 | 6994 |         return -1; | 
 | 6995 |     } | 
 | 6996 |  | 
 | 6997 |     int index1 = -1, index2 = -1; | 
 | 6998 |     for (size_t i = 0; | 
 | 6999 |             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); | 
 | 7000 |             i ++) { | 
 | 7001 |         if (sPcmFormatCompareTable[i] == format1) { | 
 | 7002 |             index1 = i; | 
 | 7003 |         } | 
 | 7004 |         if (sPcmFormatCompareTable[i] == format2) { | 
 | 7005 |             index2 = i; | 
 | 7006 |         } | 
 | 7007 |     } | 
 | 7008 |     // format1 not found => index1 < 0 => format2 > format1 | 
 | 7009 |     // format2 not found => index2 < 0 => format2 < format1 | 
 | 7010 |     return index1 - index2; | 
 | 7011 | } | 
 | 7012 |  | 
 | 7013 | audio_format_t AudioPolicyManager::AudioPort::pickFormat() const | 
 | 7014 | { | 
 | 7015 |     // special case for uninitialized dynamic profile | 
 | 7016 |     if (mFormats.size() == 1 && mFormats[0] == 0) { | 
 | 7017 |         return AUDIO_FORMAT_DEFAULT; | 
 | 7018 |     } | 
 | 7019 |  | 
 | 7020 |     audio_format_t format = AUDIO_FORMAT_DEFAULT; | 
| Andy Hung | 9a60538 | 2014-07-28 16:16:31 -0700 | [diff] [blame] | 7021 |     audio_format_t bestFormat = | 
 | 7022 |             AudioPolicyManager::AudioPort::sPcmFormatCompareTable[ | 
 | 7023 |                 ARRAY_SIZE(AudioPolicyManager::AudioPort::sPcmFormatCompareTable) - 1]; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7024 |     // For mixed output and inputs, use best mixer output format. Do not | 
 | 7025 |     // limit format otherwise | 
 | 7026 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 7027 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
| Eric Laurent | d862237 | 2014-07-27 13:47:31 -0700 | [diff] [blame] | 7028 |              (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7029 |         bestFormat = AUDIO_FORMAT_INVALID; | 
 | 7030 |     } | 
 | 7031 |  | 
 | 7032 |     for (size_t i = 0; i < mFormats.size(); i ++) { | 
 | 7033 |         if ((compareFormats(mFormats[i], format) > 0) && | 
 | 7034 |                 (compareFormats(mFormats[i], bestFormat) <= 0)) { | 
 | 7035 |             format = mFormats[i]; | 
 | 7036 |         } | 
 | 7037 |     } | 
 | 7038 |     return format; | 
 | 7039 | } | 
 | 7040 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7041 | status_t AudioPolicyManager::AudioPort::checkGain(const struct audio_gain_config *gainConfig, | 
 | 7042 |                                                   int index) const | 
 | 7043 | { | 
 | 7044 |     if (index < 0 || (size_t)index >= mGains.size()) { | 
 | 7045 |         return BAD_VALUE; | 
 | 7046 |     } | 
 | 7047 |     return mGains[index]->checkConfig(gainConfig); | 
 | 7048 | } | 
 | 7049 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7050 | void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const | 
 | 7051 | { | 
 | 7052 |     const size_t SIZE = 256; | 
 | 7053 |     char buffer[SIZE]; | 
 | 7054 |     String8 result; | 
 | 7055 |  | 
 | 7056 |     if (mName.size() != 0) { | 
 | 7057 |         snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); | 
 | 7058 |         result.append(buffer); | 
 | 7059 |     } | 
 | 7060 |  | 
 | 7061 |     if (mSamplingRates.size() != 0) { | 
 | 7062 |         snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); | 
 | 7063 |         result.append(buffer); | 
 | 7064 |         for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7065 |             if (i == 0 && mSamplingRates[i] == 0) { | 
 | 7066 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 7067 |             } else { | 
 | 7068 |                 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); | 
 | 7069 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7070 |             result.append(buffer); | 
 | 7071 |             result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); | 
 | 7072 |         } | 
 | 7073 |         result.append("\n"); | 
 | 7074 |     } | 
 | 7075 |  | 
 | 7076 |     if (mChannelMasks.size() != 0) { | 
 | 7077 |         snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); | 
 | 7078 |         result.append(buffer); | 
 | 7079 |         for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7080 |             ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]); | 
 | 7081 |  | 
 | 7082 |             if (i == 0 && mChannelMasks[i] == 0) { | 
 | 7083 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 7084 |             } else { | 
 | 7085 |                 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); | 
 | 7086 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7087 |             result.append(buffer); | 
 | 7088 |             result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); | 
 | 7089 |         } | 
 | 7090 |         result.append("\n"); | 
 | 7091 |     } | 
 | 7092 |  | 
 | 7093 |     if (mFormats.size() != 0) { | 
 | 7094 |         snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); | 
 | 7095 |         result.append(buffer); | 
 | 7096 |         for (size_t i = 0; i < mFormats.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7097 |             const char *formatStr = enumToString(sFormatNameToEnumTable, | 
 | 7098 |                                                  ARRAY_SIZE(sFormatNameToEnumTable), | 
 | 7099 |                                                  mFormats[i]); | 
 | 7100 |             if (i == 0 && strcmp(formatStr, "") == 0) { | 
 | 7101 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 7102 |             } else { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 7103 |                 snprintf(buffer, SIZE, "%s", formatStr); | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7104 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7105 |             result.append(buffer); | 
 | 7106 |             result.append(i == (mFormats.size() - 1) ? "" : ", "); | 
 | 7107 |         } | 
 | 7108 |         result.append("\n"); | 
 | 7109 |     } | 
 | 7110 |     write(fd, result.string(), result.size()); | 
 | 7111 |     if (mGains.size() != 0) { | 
 | 7112 |         snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); | 
 | 7113 |         write(fd, buffer, strlen(buffer) + 1); | 
 | 7114 |         result.append(buffer); | 
 | 7115 |         for (size_t i = 0; i < mGains.size(); i++) { | 
 | 7116 |             mGains[i]->dump(fd, spaces + 2, i); | 
 | 7117 |         } | 
 | 7118 |     } | 
 | 7119 | } | 
 | 7120 |  | 
 | 7121 | // --- AudioGain class implementation | 
 | 7122 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7123 | AudioPolicyManager::AudioGain::AudioGain(int index, bool useInChannelMask) | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7124 | { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7125 |     mIndex = index; | 
 | 7126 |     mUseInChannelMask = useInChannelMask; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7127 |     memset(&mGain, 0, sizeof(struct audio_gain)); | 
 | 7128 | } | 
 | 7129 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7130 | void AudioPolicyManager::AudioGain::getDefaultConfig(struct audio_gain_config *config) | 
 | 7131 | { | 
 | 7132 |     config->index = mIndex; | 
 | 7133 |     config->mode = mGain.mode; | 
 | 7134 |     config->channel_mask = mGain.channel_mask; | 
 | 7135 |     if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { | 
 | 7136 |         config->values[0] = mGain.default_value; | 
 | 7137 |     } else { | 
 | 7138 |         uint32_t numValues; | 
 | 7139 |         if (mUseInChannelMask) { | 
 | 7140 |             numValues = audio_channel_count_from_in_mask(mGain.channel_mask); | 
 | 7141 |         } else { | 
 | 7142 |             numValues = audio_channel_count_from_out_mask(mGain.channel_mask); | 
 | 7143 |         } | 
 | 7144 |         for (size_t i = 0; i < numValues; i++) { | 
 | 7145 |             config->values[i] = mGain.default_value; | 
 | 7146 |         } | 
 | 7147 |     } | 
 | 7148 |     if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { | 
 | 7149 |         config->ramp_duration_ms = mGain.min_ramp_ms; | 
 | 7150 |     } | 
 | 7151 | } | 
 | 7152 |  | 
 | 7153 | status_t AudioPolicyManager::AudioGain::checkConfig(const struct audio_gain_config *config) | 
 | 7154 | { | 
 | 7155 |     if ((config->mode & ~mGain.mode) != 0) { | 
 | 7156 |         return BAD_VALUE; | 
 | 7157 |     } | 
 | 7158 |     if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { | 
 | 7159 |         if ((config->values[0] < mGain.min_value) || | 
 | 7160 |                     (config->values[0] > mGain.max_value)) { | 
 | 7161 |             return BAD_VALUE; | 
 | 7162 |         } | 
 | 7163 |     } else { | 
 | 7164 |         if ((config->channel_mask & ~mGain.channel_mask) != 0) { | 
 | 7165 |             return BAD_VALUE; | 
 | 7166 |         } | 
 | 7167 |         uint32_t numValues; | 
 | 7168 |         if (mUseInChannelMask) { | 
 | 7169 |             numValues = audio_channel_count_from_in_mask(config->channel_mask); | 
 | 7170 |         } else { | 
 | 7171 |             numValues = audio_channel_count_from_out_mask(config->channel_mask); | 
 | 7172 |         } | 
 | 7173 |         for (size_t i = 0; i < numValues; i++) { | 
 | 7174 |             if ((config->values[i] < mGain.min_value) || | 
 | 7175 |                     (config->values[i] > mGain.max_value)) { | 
 | 7176 |                 return BAD_VALUE; | 
 | 7177 |             } | 
 | 7178 |         } | 
 | 7179 |     } | 
 | 7180 |     if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { | 
 | 7181 |         if ((config->ramp_duration_ms < mGain.min_ramp_ms) || | 
 | 7182 |                     (config->ramp_duration_ms > mGain.max_ramp_ms)) { | 
 | 7183 |             return BAD_VALUE; | 
 | 7184 |         } | 
 | 7185 |     } | 
 | 7186 |     return NO_ERROR; | 
 | 7187 | } | 
 | 7188 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7189 | void AudioPolicyManager::AudioGain::dump(int fd, int spaces, int index) const | 
 | 7190 | { | 
 | 7191 |     const size_t SIZE = 256; | 
 | 7192 |     char buffer[SIZE]; | 
 | 7193 |     String8 result; | 
 | 7194 |  | 
 | 7195 |     snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1); | 
 | 7196 |     result.append(buffer); | 
 | 7197 |     snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode); | 
 | 7198 |     result.append(buffer); | 
 | 7199 |     snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask); | 
 | 7200 |     result.append(buffer); | 
 | 7201 |     snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value); | 
 | 7202 |     result.append(buffer); | 
 | 7203 |     snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value); | 
 | 7204 |     result.append(buffer); | 
 | 7205 |     snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value); | 
 | 7206 |     result.append(buffer); | 
 | 7207 |     snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value); | 
 | 7208 |     result.append(buffer); | 
 | 7209 |     snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms); | 
 | 7210 |     result.append(buffer); | 
 | 7211 |     snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms); | 
 | 7212 |     result.append(buffer); | 
 | 7213 |  | 
 | 7214 |     write(fd, result.string(), result.size()); | 
 | 7215 | } | 
 | 7216 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7217 | // --- AudioPortConfig class implementation | 
 | 7218 |  | 
 | 7219 | AudioPolicyManager::AudioPortConfig::AudioPortConfig() | 
 | 7220 | { | 
 | 7221 |     mSamplingRate = 0; | 
 | 7222 |     mChannelMask = AUDIO_CHANNEL_NONE; | 
 | 7223 |     mFormat = AUDIO_FORMAT_INVALID; | 
 | 7224 |     mGain.index = -1; | 
 | 7225 | } | 
 | 7226 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7227 | status_t AudioPolicyManager::AudioPortConfig::applyAudioPortConfig( | 
 | 7228 |                                                         const struct audio_port_config *config, | 
 | 7229 |                                                         struct audio_port_config *backupConfig) | 
 | 7230 | { | 
 | 7231 |     struct audio_port_config localBackupConfig; | 
 | 7232 |     status_t status = NO_ERROR; | 
 | 7233 |  | 
 | 7234 |     localBackupConfig.config_mask = config->config_mask; | 
 | 7235 |     toAudioPortConfig(&localBackupConfig); | 
 | 7236 |  | 
| Marco Nelissen | 961ec21 | 2014-08-25 15:58:39 -0700 | [diff] [blame] | 7237 |     sp<AudioPort> audioport = getAudioPort(); | 
 | 7238 |     if (audioport == 0) { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7239 |         status = NO_INIT; | 
 | 7240 |         goto exit; | 
 | 7241 |     } | 
 | 7242 |     if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { | 
| Marco Nelissen | 961ec21 | 2014-08-25 15:58:39 -0700 | [diff] [blame] | 7243 |         status = audioport->checkExactSamplingRate(config->sample_rate); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7244 |         if (status != NO_ERROR) { | 
 | 7245 |             goto exit; | 
 | 7246 |         } | 
 | 7247 |         mSamplingRate = config->sample_rate; | 
 | 7248 |     } | 
 | 7249 |     if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { | 
| Marco Nelissen | 961ec21 | 2014-08-25 15:58:39 -0700 | [diff] [blame] | 7250 |         status = audioport->checkExactChannelMask(config->channel_mask); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7251 |         if (status != NO_ERROR) { | 
 | 7252 |             goto exit; | 
 | 7253 |         } | 
 | 7254 |         mChannelMask = config->channel_mask; | 
 | 7255 |     } | 
 | 7256 |     if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { | 
| Marco Nelissen | 961ec21 | 2014-08-25 15:58:39 -0700 | [diff] [blame] | 7257 |         status = audioport->checkFormat(config->format); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7258 |         if (status != NO_ERROR) { | 
 | 7259 |             goto exit; | 
 | 7260 |         } | 
 | 7261 |         mFormat = config->format; | 
 | 7262 |     } | 
 | 7263 |     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { | 
| Marco Nelissen | 961ec21 | 2014-08-25 15:58:39 -0700 | [diff] [blame] | 7264 |         status = audioport->checkGain(&config->gain, config->gain.index); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7265 |         if (status != NO_ERROR) { | 
 | 7266 |             goto exit; | 
 | 7267 |         } | 
 | 7268 |         mGain = config->gain; | 
 | 7269 |     } | 
 | 7270 |  | 
 | 7271 | exit: | 
 | 7272 |     if (status != NO_ERROR) { | 
 | 7273 |         applyAudioPortConfig(&localBackupConfig); | 
 | 7274 |     } | 
 | 7275 |     if (backupConfig != NULL) { | 
 | 7276 |         *backupConfig = localBackupConfig; | 
 | 7277 |     } | 
 | 7278 |     return status; | 
 | 7279 | } | 
 | 7280 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7281 | void AudioPolicyManager::AudioPortConfig::toAudioPortConfig( | 
 | 7282 |                                                     struct audio_port_config *dstConfig, | 
 | 7283 |                                                     const struct audio_port_config *srcConfig) const | 
 | 7284 | { | 
 | 7285 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { | 
 | 7286 |         dstConfig->sample_rate = mSamplingRate; | 
 | 7287 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { | 
 | 7288 |             dstConfig->sample_rate = srcConfig->sample_rate; | 
 | 7289 |         } | 
 | 7290 |     } else { | 
 | 7291 |         dstConfig->sample_rate = 0; | 
 | 7292 |     } | 
 | 7293 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { | 
 | 7294 |         dstConfig->channel_mask = mChannelMask; | 
 | 7295 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { | 
 | 7296 |             dstConfig->channel_mask = srcConfig->channel_mask; | 
 | 7297 |         } | 
 | 7298 |     } else { | 
 | 7299 |         dstConfig->channel_mask = AUDIO_CHANNEL_NONE; | 
 | 7300 |     } | 
 | 7301 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { | 
 | 7302 |         dstConfig->format = mFormat; | 
 | 7303 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { | 
 | 7304 |             dstConfig->format = srcConfig->format; | 
 | 7305 |         } | 
 | 7306 |     } else { | 
 | 7307 |         dstConfig->format = AUDIO_FORMAT_INVALID; | 
 | 7308 |     } | 
 | 7309 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) { | 
 | 7310 |         dstConfig->gain = mGain; | 
 | 7311 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) { | 
 | 7312 |             dstConfig->gain = srcConfig->gain; | 
 | 7313 |         } | 
 | 7314 |     } else { | 
 | 7315 |         dstConfig->gain.index = -1; | 
 | 7316 |     } | 
 | 7317 |     if (dstConfig->gain.index != -1) { | 
 | 7318 |         dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; | 
 | 7319 |     } else { | 
 | 7320 |         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; | 
 | 7321 |     } | 
 | 7322 | } | 
 | 7323 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7324 | // --- IOProfile class implementation | 
 | 7325 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7326 | AudioPolicyManager::IOProfile::IOProfile(const String8& name, audio_port_role_t role, | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7327 |                                          const sp<HwModule>& module) | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7328 |     : AudioPort(name, AUDIO_PORT_TYPE_MIX, role, module) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7329 | { | 
 | 7330 | } | 
 | 7331 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7332 | AudioPolicyManager::IOProfile::~IOProfile() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7333 | { | 
 | 7334 | } | 
 | 7335 |  | 
 | 7336 | // checks if the IO profile is compatible with specified parameters. | 
 | 7337 | // Sampling rate, format and channel mask must be specified in order to | 
 | 7338 | // get a valid a match | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7339 | bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device, | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 7340 |                                                         String8 address, | 
 | 7341 |                                                         uint32_t samplingRate, | 
 | 7342 |                                                         uint32_t *updatedSamplingRate, | 
 | 7343 |                                                         audio_format_t format, | 
 | 7344 |                                                         audio_channel_mask_t channelMask, | 
 | 7345 |                                                         uint32_t flags) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7346 | { | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 7347 |     const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE; | 
 | 7348 |     const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; | 
 | 7349 |     ALOG_ASSERT(isPlaybackThread != isRecordThread); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7350 |  | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 7351 |     if (device != AUDIO_DEVICE_NONE && mSupportedDevices.getDevice(device, address) == 0) { | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 7352 |         return false; | 
 | 7353 |     } | 
 | 7354 |  | 
 | 7355 |     if (samplingRate == 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7356 |          return false; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 7357 |     } | 
 | 7358 |     uint32_t myUpdatedSamplingRate = samplingRate; | 
 | 7359 |     if (isPlaybackThread && checkExactSamplingRate(samplingRate) != NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7360 |          return false; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 7361 |     } | 
 | 7362 |     if (isRecordThread && checkCompatibleSamplingRate(samplingRate, &myUpdatedSamplingRate) != | 
 | 7363 |             NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7364 |          return false; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 7365 |     } | 
 | 7366 |  | 
 | 7367 |     if (!audio_is_valid_format(format) || checkFormat(format) != NO_ERROR) { | 
 | 7368 |         return false; | 
 | 7369 |     } | 
 | 7370 |  | 
 | 7371 |     if (isPlaybackThread && (!audio_is_output_channel(channelMask) || | 
 | 7372 |             checkExactChannelMask(channelMask) != NO_ERROR)) { | 
 | 7373 |         return false; | 
 | 7374 |     } | 
 | 7375 |     if (isRecordThread && (!audio_is_input_channel(channelMask) || | 
 | 7376 |             checkCompatibleChannelMask(channelMask) != NO_ERROR)) { | 
 | 7377 |         return false; | 
 | 7378 |     } | 
 | 7379 |  | 
 | 7380 |     if (isPlaybackThread && (mFlags & flags) != flags) { | 
 | 7381 |         return false; | 
 | 7382 |     } | 
 | 7383 |     // The only input flag that is allowed to be different is the fast flag. | 
 | 7384 |     // An existing fast stream is compatible with a normal track request. | 
 | 7385 |     // An existing normal stream is compatible with a fast track request, | 
 | 7386 |     // but the fast request will be denied by AudioFlinger and converted to normal track. | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 7387 |     if (isRecordThread && ((mFlags ^ flags) & | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 7388 |             ~AUDIO_INPUT_FLAG_FAST)) { | 
 | 7389 |         return false; | 
 | 7390 |     } | 
 | 7391 |  | 
 | 7392 |     if (updatedSamplingRate != NULL) { | 
 | 7393 |         *updatedSamplingRate = myUpdatedSamplingRate; | 
 | 7394 |     } | 
 | 7395 |     return true; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7396 | } | 
 | 7397 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7398 | void AudioPolicyManager::IOProfile::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7399 | { | 
 | 7400 |     const size_t SIZE = 256; | 
 | 7401 |     char buffer[SIZE]; | 
 | 7402 |     String8 result; | 
 | 7403 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7404 |     AudioPort::dump(fd, 4); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7405 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7406 |     snprintf(buffer, SIZE, "    - flags: 0x%04x\n", mFlags); | 
 | 7407 |     result.append(buffer); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7408 |     snprintf(buffer, SIZE, "    - devices:\n"); | 
 | 7409 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7410 |     write(fd, result.string(), result.size()); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7411 |     for (size_t i = 0; i < mSupportedDevices.size(); i++) { | 
 | 7412 |         mSupportedDevices[i]->dump(fd, 6, i); | 
 | 7413 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7414 | } | 
 | 7415 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 7416 | void AudioPolicyManager::IOProfile::log() | 
 | 7417 | { | 
 | 7418 |     const size_t SIZE = 256; | 
 | 7419 |     char buffer[SIZE]; | 
 | 7420 |     String8 result; | 
 | 7421 |  | 
 | 7422 |     ALOGV("    - sampling rates: "); | 
 | 7423 |     for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
 | 7424 |         ALOGV("  %d", mSamplingRates[i]); | 
 | 7425 |     } | 
 | 7426 |  | 
 | 7427 |     ALOGV("    - channel masks: "); | 
 | 7428 |     for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
 | 7429 |         ALOGV("  0x%04x", mChannelMasks[i]); | 
 | 7430 |     } | 
 | 7431 |  | 
 | 7432 |     ALOGV("    - formats: "); | 
 | 7433 |     for (size_t i = 0; i < mFormats.size(); i++) { | 
 | 7434 |         ALOGV("  0x%08x", mFormats[i]); | 
 | 7435 |     } | 
 | 7436 |  | 
 | 7437 |     ALOGV("    - devices: 0x%04x\n", mSupportedDevices.types()); | 
 | 7438 |     ALOGV("    - flags: 0x%04x\n", mFlags); | 
 | 7439 | } | 
 | 7440 |  | 
 | 7441 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7442 | // --- DeviceDescriptor implementation | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7443 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7444 |  | 
 | 7445 | AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) : | 
 | 7446 |                      AudioPort(name, AUDIO_PORT_TYPE_DEVICE, | 
 | 7447 |                                audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : | 
 | 7448 |                                                               AUDIO_PORT_ROLE_SOURCE, | 
 | 7449 |                              NULL), | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 7450 |                      mDeviceType(type), mAddress(""), mId(0) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7451 | { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 7452 |     if (mGains.size() > 0) { | 
 | 7453 |         mGains[0]->getDefaultConfig(&mGain); | 
 | 7454 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7455 | } | 
 | 7456 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7457 | bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7458 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7459 |     // Devices are considered equal if they: | 
 | 7460 |     // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE) | 
 | 7461 |     // - have the same address or one device does not specify the address | 
 | 7462 |     // - have the same channel mask or one device does not specify the channel mask | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7463 |     return (mDeviceType == other->mDeviceType) && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7464 |            (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) && | 
| Eric Laurent | 2f8a36f | 2014-03-26 19:05:55 -0700 | [diff] [blame] | 7465 |            (mChannelMask == 0 || other->mChannelMask == 0 || | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7466 |                 mChannelMask == other->mChannelMask); | 
 | 7467 | } | 
 | 7468 |  | 
 | 7469 | void AudioPolicyManager::DeviceVector::refreshTypes() | 
 | 7470 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7471 |     mDeviceTypes = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7472 |     for(size_t i = 0; i < size(); i++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7473 |         mDeviceTypes |= itemAt(i)->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7474 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7475 |     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7476 | } | 
 | 7477 |  | 
 | 7478 | ssize_t AudioPolicyManager::DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const | 
 | 7479 | { | 
 | 7480 |     for(size_t i = 0; i < size(); i++) { | 
 | 7481 |         if (item->equals(itemAt(i))) { | 
 | 7482 |             return i; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7483 |         } | 
 | 7484 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7485 |     return -1; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7486 | } | 
 | 7487 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7488 | ssize_t AudioPolicyManager::DeviceVector::add(const sp<DeviceDescriptor>& item) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7489 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7490 |     ssize_t ret = indexOf(item); | 
 | 7491 |  | 
 | 7492 |     if (ret < 0) { | 
 | 7493 |         ret = SortedVector::add(item); | 
 | 7494 |         if (ret >= 0) { | 
 | 7495 |             refreshTypes(); | 
 | 7496 |         } | 
 | 7497 |     } else { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7498 |         ALOGW("DeviceVector::add device %08x already in", item->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7499 |         ret = -1; | 
 | 7500 |     } | 
 | 7501 |     return ret; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7502 | } | 
 | 7503 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7504 | ssize_t AudioPolicyManager::DeviceVector::remove(const sp<DeviceDescriptor>& item) | 
 | 7505 | { | 
 | 7506 |     size_t i; | 
 | 7507 |     ssize_t ret = indexOf(item); | 
 | 7508 |  | 
 | 7509 |     if (ret < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7510 |         ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7511 |     } else { | 
 | 7512 |         ret = SortedVector::removeAt(ret); | 
 | 7513 |         if (ret >= 0) { | 
 | 7514 |             refreshTypes(); | 
 | 7515 |         } | 
 | 7516 |     } | 
 | 7517 |     return ret; | 
 | 7518 | } | 
 | 7519 |  | 
 | 7520 | void AudioPolicyManager::DeviceVector::loadDevicesFromType(audio_devices_t types) | 
 | 7521 | { | 
 | 7522 |     DeviceVector deviceList; | 
 | 7523 |  | 
 | 7524 |     uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types; | 
 | 7525 |     types &= ~role_bit; | 
 | 7526 |  | 
 | 7527 |     while (types) { | 
 | 7528 |         uint32_t i = 31 - __builtin_clz(types); | 
 | 7529 |         uint32_t type = 1 << i; | 
 | 7530 |         types &= ~type; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7531 |         add(new DeviceDescriptor(String8(""), type | role_bit)); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7532 |     } | 
 | 7533 | } | 
 | 7534 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7535 | void AudioPolicyManager::DeviceVector::loadDevicesFromName(char *name, | 
 | 7536 |                                                            const DeviceVector& declaredDevices) | 
 | 7537 | { | 
 | 7538 |     char *devName = strtok(name, "|"); | 
 | 7539 |     while (devName != NULL) { | 
 | 7540 |         if (strlen(devName) != 0) { | 
 | 7541 |             audio_devices_t type = stringToEnum(sDeviceNameToEnumTable, | 
 | 7542 |                                  ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 7543 |                                  devName); | 
 | 7544 |             if (type != AUDIO_DEVICE_NONE) { | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 7545 |                 sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(""), type); | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 7546 |                 if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX || | 
 | 7547 |                         type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) { | 
| Jean-Michel Trivi | fd4c148 | 2014-08-06 16:02:28 -0700 | [diff] [blame] | 7548 |                     dev->mAddress = String8("0"); | 
 | 7549 |                 } | 
 | 7550 |                 add(dev); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7551 |             } else { | 
 | 7552 |                 sp<DeviceDescriptor> deviceDesc = | 
 | 7553 |                         declaredDevices.getDeviceFromName(String8(devName)); | 
 | 7554 |                 if (deviceDesc != 0) { | 
 | 7555 |                     add(deviceDesc); | 
 | 7556 |                 } | 
 | 7557 |             } | 
 | 7558 |          } | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 7559 |          devName = strtok(NULL, "|"); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7560 |      } | 
 | 7561 | } | 
 | 7562 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7563 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDevice( | 
 | 7564 |                                                         audio_devices_t type, String8 address) const | 
 | 7565 | { | 
 | 7566 |     sp<DeviceDescriptor> device; | 
 | 7567 |     for (size_t i = 0; i < size(); i++) { | 
 | 7568 |         if (itemAt(i)->mDeviceType == type) { | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 7569 |             if (address == "" || itemAt(i)->mAddress == address) { | 
 | 7570 |                 device = itemAt(i); | 
 | 7571 |                 if (itemAt(i)->mAddress == address) { | 
 | 7572 |                     break; | 
 | 7573 |                 } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7574 |             } | 
 | 7575 |         } | 
 | 7576 |     } | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 7577 |     ALOGV("DeviceVector::getDevice() for type %08x address %s found %p", | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7578 |           type, address.string(), device.get()); | 
 | 7579 |     return device; | 
 | 7580 | } | 
 | 7581 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7582 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromId( | 
 | 7583 |                                                                     audio_port_handle_t id) const | 
 | 7584 | { | 
 | 7585 |     sp<DeviceDescriptor> device; | 
 | 7586 |     for (size_t i = 0; i < size(); i++) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 7587 |         ALOGV("DeviceVector::getDeviceFromId(%d) itemAt(%zu)->mId %d", id, i, itemAt(i)->mId); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7588 |         if (itemAt(i)->mId == id) { | 
 | 7589 |             device = itemAt(i); | 
 | 7590 |             break; | 
 | 7591 |         } | 
 | 7592 |     } | 
 | 7593 |     return device; | 
 | 7594 | } | 
 | 7595 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7596 | AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromType( | 
 | 7597 |                                                                         audio_devices_t type) const | 
 | 7598 | { | 
 | 7599 |     DeviceVector devices; | 
 | 7600 |     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) { | 
 | 7601 |         if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) { | 
 | 7602 |             devices.add(itemAt(i)); | 
 | 7603 |             type &= ~itemAt(i)->mDeviceType; | 
 | 7604 |             ALOGV("DeviceVector::getDevicesFromType() for type %x found %p", | 
 | 7605 |                   itemAt(i)->mDeviceType, itemAt(i).get()); | 
 | 7606 |         } | 
 | 7607 |     } | 
 | 7608 |     return devices; | 
 | 7609 | } | 
 | 7610 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 7611 | AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromTypeAddr( | 
 | 7612 |         audio_devices_t type, String8 address) const | 
 | 7613 | { | 
 | 7614 |     DeviceVector devices; | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 7615 |     for (size_t i = 0; i < size(); i++) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 7616 |         if (itemAt(i)->mDeviceType == type) { | 
 | 7617 |             if (itemAt(i)->mAddress == address) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 7618 |                 devices.add(itemAt(i)); | 
 | 7619 |             } | 
 | 7620 |         } | 
 | 7621 |     } | 
 | 7622 |     return devices; | 
 | 7623 | } | 
 | 7624 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7625 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromName( | 
 | 7626 |         const String8& name) const | 
 | 7627 | { | 
 | 7628 |     sp<DeviceDescriptor> device; | 
 | 7629 |     for (size_t i = 0; i < size(); i++) { | 
 | 7630 |         if (itemAt(i)->mName == name) { | 
 | 7631 |             device = itemAt(i); | 
 | 7632 |             break; | 
 | 7633 |         } | 
 | 7634 |     } | 
 | 7635 |     return device; | 
 | 7636 | } | 
 | 7637 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7638 | void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig( | 
 | 7639 |                                                     struct audio_port_config *dstConfig, | 
 | 7640 |                                                     const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7641 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7642 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK|AUDIO_PORT_CONFIG_GAIN; | 
 | 7643 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 7644 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7645 |     } | 
 | 7646 |  | 
 | 7647 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 7648 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7649 |     dstConfig->id = mId; | 
 | 7650 |     dstConfig->role = audio_is_output_device(mDeviceType) ? | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7651 |                         AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7652 |     dstConfig->type = AUDIO_PORT_TYPE_DEVICE; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7653 |     dstConfig->ext.device.type = mDeviceType; | 
 | 7654 |     dstConfig->ext.device.hw_module = mModule->mHandle; | 
 | 7655 |     strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7656 | } | 
 | 7657 |  | 
 | 7658 | void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const | 
 | 7659 | { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 7660 |     ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7661 |     AudioPort::toAudioPort(port); | 
 | 7662 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7663 |     toAudioPortConfig(&port->active_config); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7664 |     port->ext.device.type = mDeviceType; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 7665 |     port->ext.device.hw_module = mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7666 |     strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); | 
 | 7667 | } | 
 | 7668 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7669 | status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces, int index) const | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7670 | { | 
 | 7671 |     const size_t SIZE = 256; | 
 | 7672 |     char buffer[SIZE]; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7673 |     String8 result; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7674 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7675 |     snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1); | 
 | 7676 |     result.append(buffer); | 
 | 7677 |     if (mId != 0) { | 
 | 7678 |         snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId); | 
 | 7679 |         result.append(buffer); | 
 | 7680 |     } | 
 | 7681 |     snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "", | 
 | 7682 |                                               enumToString(sDeviceNameToEnumTable, | 
 | 7683 |                                                            ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 7684 |                                                            mDeviceType)); | 
 | 7685 |     result.append(buffer); | 
 | 7686 |     if (mAddress.size() != 0) { | 
 | 7687 |         snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string()); | 
 | 7688 |         result.append(buffer); | 
 | 7689 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7690 |     write(fd, result.string(), result.size()); | 
 | 7691 |     AudioPort::dump(fd, spaces); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7692 |  | 
 | 7693 |     return NO_ERROR; | 
 | 7694 | } | 
 | 7695 |  | 
| Eric Laurent | 4d41695 | 2014-08-10 14:07:09 -0700 | [diff] [blame] | 7696 | status_t AudioPolicyManager::AudioPatch::dump(int fd, int spaces, int index) const | 
 | 7697 | { | 
 | 7698 |     const size_t SIZE = 256; | 
 | 7699 |     char buffer[SIZE]; | 
 | 7700 |     String8 result; | 
 | 7701 |  | 
 | 7702 |  | 
 | 7703 |     snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1); | 
 | 7704 |     result.append(buffer); | 
 | 7705 |     snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle); | 
 | 7706 |     result.append(buffer); | 
 | 7707 |     snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle); | 
 | 7708 |     result.append(buffer); | 
 | 7709 |     snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid); | 
 | 7710 |     result.append(buffer); | 
 | 7711 |     snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources); | 
 | 7712 |     result.append(buffer); | 
 | 7713 |     for (size_t i = 0; i < mPatch.num_sources; i++) { | 
 | 7714 |         if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 7715 |             snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "", | 
 | 7716 |                      mPatch.sources[i].id, enumToString(sDeviceNameToEnumTable, | 
 | 7717 |                                                         ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 7718 |                                                         mPatch.sources[i].ext.device.type)); | 
 | 7719 |         } else { | 
 | 7720 |             snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "", | 
 | 7721 |                      mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle); | 
 | 7722 |         } | 
 | 7723 |         result.append(buffer); | 
 | 7724 |     } | 
 | 7725 |     snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks); | 
 | 7726 |     result.append(buffer); | 
 | 7727 |     for (size_t i = 0; i < mPatch.num_sinks; i++) { | 
 | 7728 |         if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 7729 |             snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "", | 
 | 7730 |                      mPatch.sinks[i].id, enumToString(sDeviceNameToEnumTable, | 
 | 7731 |                                                         ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 7732 |                                                         mPatch.sinks[i].ext.device.type)); | 
 | 7733 |         } else { | 
 | 7734 |             snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "", | 
 | 7735 |                      mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle); | 
 | 7736 |         } | 
 | 7737 |         result.append(buffer); | 
 | 7738 |     } | 
 | 7739 |  | 
 | 7740 |     write(fd, result.string(), result.size()); | 
 | 7741 |     return NO_ERROR; | 
 | 7742 | } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7743 |  | 
 | 7744 | // --- audio_policy.conf file parsing | 
 | 7745 |  | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 7746 | uint32_t AudioPolicyManager::parseOutputFlagNames(char *name) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7747 | { | 
 | 7748 |     uint32_t flag = 0; | 
 | 7749 |  | 
 | 7750 |     // it is OK to cast name to non const here as we are not going to use it after | 
 | 7751 |     // strtok() modifies it | 
 | 7752 |     char *flagName = strtok(name, "|"); | 
 | 7753 |     while (flagName != NULL) { | 
 | 7754 |         if (strlen(flagName) != 0) { | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 7755 |             flag |= stringToEnum(sOutputFlagNameToEnumTable, | 
 | 7756 |                                ARRAY_SIZE(sOutputFlagNameToEnumTable), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7757 |                                flagName); | 
 | 7758 |         } | 
 | 7759 |         flagName = strtok(NULL, "|"); | 
 | 7760 |     } | 
 | 7761 |     //force direct flag if offload flag is set: offloading implies a direct output stream | 
 | 7762 |     // and all common behaviors are driven by checking only the direct flag | 
 | 7763 |     // this should normally be set appropriately in the policy configuration file | 
 | 7764 |     if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
 | 7765 |         flag |= AUDIO_OUTPUT_FLAG_DIRECT; | 
 | 7766 |     } | 
 | 7767 |  | 
| Eric Laurent | 5dbe471 | 2014-09-19 19:04:57 -0700 | [diff] [blame] | 7768 |     return flag; | 
 | 7769 | } | 
 | 7770 |  | 
 | 7771 | uint32_t AudioPolicyManager::parseInputFlagNames(char *name) | 
 | 7772 | { | 
 | 7773 |     uint32_t flag = 0; | 
 | 7774 |  | 
 | 7775 |     // it is OK to cast name to non const here as we are not going to use it after | 
 | 7776 |     // strtok() modifies it | 
 | 7777 |     char *flagName = strtok(name, "|"); | 
 | 7778 |     while (flagName != NULL) { | 
 | 7779 |         if (strlen(flagName) != 0) { | 
 | 7780 |             flag |= stringToEnum(sInputFlagNameToEnumTable, | 
 | 7781 |                                ARRAY_SIZE(sInputFlagNameToEnumTable), | 
 | 7782 |                                flagName); | 
 | 7783 |         } | 
 | 7784 |         flagName = strtok(NULL, "|"); | 
 | 7785 |     } | 
 | 7786 |     return flag; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7787 | } | 
 | 7788 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7789 | audio_devices_t AudioPolicyManager::parseDeviceNames(char *name) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7790 | { | 
 | 7791 |     uint32_t device = 0; | 
 | 7792 |  | 
 | 7793 |     char *devName = strtok(name, "|"); | 
 | 7794 |     while (devName != NULL) { | 
 | 7795 |         if (strlen(devName) != 0) { | 
 | 7796 |             device |= stringToEnum(sDeviceNameToEnumTable, | 
 | 7797 |                                  ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 7798 |                                  devName); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7799 |          } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7800 |         devName = strtok(NULL, "|"); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7801 |      } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7802 |     return device; | 
 | 7803 | } | 
 | 7804 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7805 | void AudioPolicyManager::loadHwModule(cnode *root) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7806 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7807 |     status_t status = NAME_NOT_FOUND; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7808 |     cnode *node; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7809 |     sp<HwModule> module = new HwModule(root->name); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7810 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7811 |     node = config_find(root, DEVICES_TAG); | 
 | 7812 |     if (node != NULL) { | 
 | 7813 |         node = node->first_child; | 
 | 7814 |         while (node) { | 
 | 7815 |             ALOGV("loadHwModule() loading device %s", node->name); | 
 | 7816 |             status_t tmpStatus = module->loadDevice(node); | 
 | 7817 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 7818 |                 status = tmpStatus; | 
 | 7819 |             } | 
 | 7820 |             node = node->next; | 
 | 7821 |         } | 
 | 7822 |     } | 
 | 7823 |     node = config_find(root, OUTPUTS_TAG); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7824 |     if (node != NULL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7825 |         node = node->first_child; | 
 | 7826 |         while (node) { | 
 | 7827 |             ALOGV("loadHwModule() loading output %s", node->name); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7828 |             status_t tmpStatus = module->loadOutput(node); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7829 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 7830 |                 status = tmpStatus; | 
 | 7831 |             } | 
 | 7832 |             node = node->next; | 
 | 7833 |         } | 
 | 7834 |     } | 
 | 7835 |     node = config_find(root, INPUTS_TAG); | 
 | 7836 |     if (node != NULL) { | 
 | 7837 |         node = node->first_child; | 
 | 7838 |         while (node) { | 
 | 7839 |             ALOGV("loadHwModule() loading input %s", node->name); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7840 |             status_t tmpStatus = module->loadInput(node); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7841 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 7842 |                 status = tmpStatus; | 
 | 7843 |             } | 
 | 7844 |             node = node->next; | 
 | 7845 |         } | 
 | 7846 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7847 |     loadGlobalConfig(root, module); | 
 | 7848 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7849 |     if (status == NO_ERROR) { | 
 | 7850 |         mHwModules.add(module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7851 |     } | 
 | 7852 | } | 
 | 7853 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7854 | void AudioPolicyManager::loadHwModules(cnode *root) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7855 | { | 
 | 7856 |     cnode *node = config_find(root, AUDIO_HW_MODULE_TAG); | 
 | 7857 |     if (node == NULL) { | 
 | 7858 |         return; | 
 | 7859 |     } | 
 | 7860 |  | 
 | 7861 |     node = node->first_child; | 
 | 7862 |     while (node) { | 
 | 7863 |         ALOGV("loadHwModules() loading module %s", node->name); | 
 | 7864 |         loadHwModule(node); | 
 | 7865 |         node = node->next; | 
 | 7866 |     } | 
 | 7867 | } | 
 | 7868 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7869 | void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7870 | { | 
 | 7871 |     cnode *node = config_find(root, GLOBAL_CONFIG_TAG); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 7872 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7873 |     if (node == NULL) { | 
 | 7874 |         return; | 
 | 7875 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7876 |     DeviceVector declaredDevices; | 
 | 7877 |     if (module != NULL) { | 
 | 7878 |         declaredDevices = module->mDeclaredDevices; | 
 | 7879 |     } | 
 | 7880 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7881 |     node = node->first_child; | 
 | 7882 |     while (node) { | 
 | 7883 |         if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7884 |             mAvailableOutputDevices.loadDevicesFromName((char *)node->value, | 
 | 7885 |                                                         declaredDevices); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7886 |             ALOGV("loadGlobalConfig() Attached Output Devices %08x", | 
 | 7887 |                   mAvailableOutputDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7888 |         } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7889 |             audio_devices_t device = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7890 |                                               ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 7891 |                                               (char *)node->value); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7892 |             if (device != AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7893 |                 mDefaultOutputDevice = new DeviceDescriptor(String8(""), device); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7894 |             } else { | 
 | 7895 |                 ALOGW("loadGlobalConfig() default device not specified"); | 
 | 7896 |             } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7897 |             ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7898 |         } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7899 |             mAvailableInputDevices.loadDevicesFromName((char *)node->value, | 
 | 7900 |                                                        declaredDevices); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7901 |             ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7902 |         } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { | 
 | 7903 |             mSpeakerDrcEnabled = stringToBool((char *)node->value); | 
 | 7904 |             ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 7905 |         } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) { | 
 | 7906 |             uint32_t major, minor; | 
 | 7907 |             sscanf((char *)node->value, "%u.%u", &major, &minor); | 
 | 7908 |             module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor); | 
 | 7909 |             ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u", | 
 | 7910 |                   module->mHalVersion, major, minor); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7911 |         } | 
 | 7912 |         node = node->next; | 
 | 7913 |     } | 
 | 7914 | } | 
 | 7915 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7916 | status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7917 | { | 
 | 7918 |     cnode *root; | 
 | 7919 |     char *data; | 
 | 7920 |  | 
 | 7921 |     data = (char *)load_file(path, NULL); | 
 | 7922 |     if (data == NULL) { | 
 | 7923 |         return -ENODEV; | 
 | 7924 |     } | 
 | 7925 |     root = config_node("", ""); | 
 | 7926 |     config_load(root, data); | 
 | 7927 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7928 |     loadHwModules(root); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7929 |     // legacy audio_policy.conf files have one global_configuration section | 
 | 7930 |     loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7931 |     config_free(root); | 
 | 7932 |     free(root); | 
 | 7933 |     free(data); | 
 | 7934 |  | 
 | 7935 |     ALOGI("loadAudioPolicyConfig() loaded %s\n", path); | 
 | 7936 |  | 
 | 7937 |     return NO_ERROR; | 
 | 7938 | } | 
 | 7939 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 7940 | void AudioPolicyManager::defaultAudioPolicyConfig(void) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7941 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7942 |     sp<HwModule> module; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 7943 |     sp<IOProfile> profile; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 7944 |     sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""), | 
 | 7945 |                                                                    AUDIO_DEVICE_IN_BUILTIN_MIC); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7946 |     mAvailableOutputDevices.add(mDefaultOutputDevice); | 
 | 7947 |     mAvailableInputDevices.add(defaultInputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7948 |  | 
 | 7949 |     module = new HwModule("primary"); | 
 | 7950 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7951 |     profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE, module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7952 |     profile->mSamplingRates.add(44100); | 
 | 7953 |     profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); | 
 | 7954 |     profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7955 |     profile->mSupportedDevices.add(mDefaultOutputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7956 |     profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY; | 
 | 7957 |     module->mOutputProfiles.add(profile); | 
 | 7958 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 7959 |     profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK, module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7960 |     profile->mSamplingRates.add(8000); | 
 | 7961 |     profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); | 
 | 7962 |     profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 7963 |     profile->mSupportedDevices.add(defaultInputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 7964 |     module->mInputProfiles.add(profile); | 
 | 7965 |  | 
 | 7966 |     mHwModules.add(module); | 
 | 7967 | } | 
 | 7968 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 7969 | audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr) | 
 | 7970 | { | 
 | 7971 |     // flags to stream type mapping | 
 | 7972 |     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { | 
 | 7973 |         return AUDIO_STREAM_ENFORCED_AUDIBLE; | 
 | 7974 |     } | 
 | 7975 |     if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) { | 
 | 7976 |         return AUDIO_STREAM_BLUETOOTH_SCO; | 
 | 7977 |     } | 
 | 7978 |  | 
 | 7979 |     // usage to stream type mapping | 
 | 7980 |     switch (attr->usage) { | 
 | 7981 |     case AUDIO_USAGE_MEDIA: | 
 | 7982 |     case AUDIO_USAGE_GAME: | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 7983 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 7984 |         return AUDIO_STREAM_MUSIC; | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 7985 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 7986 |         if (isStreamActive(AUDIO_STREAM_ALARM)) { | 
 | 7987 |             return AUDIO_STREAM_ALARM; | 
 | 7988 |         } | 
 | 7989 |         if (isStreamActive(AUDIO_STREAM_RING)) { | 
 | 7990 |             return AUDIO_STREAM_RING; | 
 | 7991 |         } | 
 | 7992 |         if (isInCall()) { | 
 | 7993 |             return AUDIO_STREAM_VOICE_CALL; | 
 | 7994 |         } | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 7995 |         return AUDIO_STREAM_ACCESSIBILITY; | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 7996 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 7997 |         return AUDIO_STREAM_SYSTEM; | 
 | 7998 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 7999 |         return AUDIO_STREAM_VOICE_CALL; | 
 | 8000 |  | 
 | 8001 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 8002 |         return AUDIO_STREAM_DTMF; | 
 | 8003 |  | 
 | 8004 |     case AUDIO_USAGE_ALARM: | 
 | 8005 |         return AUDIO_STREAM_ALARM; | 
 | 8006 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 8007 |         return AUDIO_STREAM_RING; | 
 | 8008 |  | 
 | 8009 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 8010 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 8011 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 8012 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 8013 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 8014 |         return AUDIO_STREAM_NOTIFICATION; | 
 | 8015 |  | 
 | 8016 |     case AUDIO_USAGE_UNKNOWN: | 
 | 8017 |     default: | 
 | 8018 |         return AUDIO_STREAM_MUSIC; | 
 | 8019 |     } | 
 | 8020 | } | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 8021 |  | 
 | 8022 | bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) { | 
 | 8023 |     // has flags that map to a strategy? | 
 | 8024 |     if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) { | 
 | 8025 |         return true; | 
 | 8026 |     } | 
 | 8027 |  | 
 | 8028 |     // has known usage? | 
 | 8029 |     switch (paa->usage) { | 
 | 8030 |     case AUDIO_USAGE_UNKNOWN: | 
 | 8031 |     case AUDIO_USAGE_MEDIA: | 
 | 8032 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 8033 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 8034 |     case AUDIO_USAGE_ALARM: | 
 | 8035 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 8036 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 8037 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 8038 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 8039 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 8040 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 8041 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
 | 8042 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 8043 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 8044 |     case AUDIO_USAGE_GAME: | 
| Eric Laurent | 275e8e9 | 2014-11-30 15:14:47 -0800 | [diff] [blame] | 8045 |     case AUDIO_USAGE_VIRTUAL_SOURCE: | 
| Eric Laurent | e83b55d | 2014-11-14 10:06:21 -0800 | [diff] [blame] | 8046 |         break; | 
 | 8047 |     default: | 
 | 8048 |         return false; | 
 | 8049 |     } | 
 | 8050 |     return true; | 
 | 8051 | } | 
 | 8052 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 8053 | }; // namespace android |