| 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() | 
 | 29 | #define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  AUDIO_DEVICE_IN_REMOTE_SUBMIX | 
 | 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 | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 46 | #include "AudioPolicyManager.h" | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 47 | #include "audio_policy_conf.h" | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 48 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 49 | namespace android { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 50 |  | 
 | 51 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 52 | // Definitions for audio_policy.conf file parsing | 
 | 53 | // ---------------------------------------------------------------------------- | 
 | 54 |  | 
 | 55 | struct StringToEnum { | 
 | 56 |     const char *name; | 
 | 57 |     uint32_t value; | 
 | 58 | }; | 
 | 59 |  | 
 | 60 | #define STRING_TO_ENUM(string) { #string, string } | 
 | 61 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | 
 | 62 |  | 
 | 63 | const StringToEnum sDeviceNameToEnumTable[] = { | 
 | 64 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE), | 
 | 65 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER), | 
 | 66 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET), | 
 | 67 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE), | 
 | 68 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO), | 
 | 69 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET), | 
 | 70 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT), | 
 | 71 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO), | 
 | 72 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP), | 
 | 73 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES), | 
 | 74 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), | 
 | 75 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP), | 
 | 76 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 77 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 78 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET), | 
 | 79 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET), | 
 | 80 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY), | 
 | 81 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE), | 
 | 82 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB), | 
 | 83 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 84 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX), | 
 | 85 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE), | 
 | 86 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC), | 
 | 87 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF), | 
 | 88 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM), | 
| Eric Laurent | e1d37b7 | 2014-07-29 10:26:26 -0700 | [diff] [blame^] | 89 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 90 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), | 
 | 91 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), | 
 | 92 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO), | 
 | 93 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET), | 
 | 94 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 95 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 96 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 97 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 98 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC), | 
 | 99 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX), | 
 | 100 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET), | 
 | 101 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET), | 
 | 102 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY), | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 103 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 104 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER), | 
 | 105 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER), | 
 | 106 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE), | 
 | 107 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF), | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 108 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP), | 
| Terry Heo | 7999a22 | 2014-06-27 15:23:36 +0900 | [diff] [blame] | 109 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 110 | }; | 
 | 111 |  | 
 | 112 | const StringToEnum sFlagNameToEnumTable[] = { | 
 | 113 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT), | 
 | 114 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY), | 
 | 115 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST), | 
 | 116 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), | 
 | 117 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), | 
 | 118 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING), | 
 | 119 | }; | 
 | 120 |  | 
 | 121 | const StringToEnum sFormatNameToEnumTable[] = { | 
 | 122 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT), | 
 | 123 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT), | 
 | 124 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT), | 
 | 125 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT), | 
 | 126 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT), | 
 | 127 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED), | 
 | 128 |     STRING_TO_ENUM(AUDIO_FORMAT_MP3), | 
 | 129 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC), | 
| aarti jadhav-gaikwad | 2829edc | 2014-06-18 15:25:26 +0530 | [diff] [blame] | 130 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_MAIN), | 
 | 131 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC), | 
 | 132 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_SSR), | 
 | 133 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LTP), | 
 | 134 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1), | 
 | 135 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_SCALABLE), | 
 | 136 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ERLC), | 
 | 137 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LD), | 
 | 138 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2), | 
 | 139 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ELD), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 140 |     STRING_TO_ENUM(AUDIO_FORMAT_VORBIS), | 
| Eric Laurent | ab5cdba | 2014-06-09 17:22:27 -0700 | [diff] [blame] | 141 |     STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1), | 
 | 142 |     STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2), | 
 | 143 |     STRING_TO_ENUM(AUDIO_FORMAT_OPUS), | 
 | 144 |     STRING_TO_ENUM(AUDIO_FORMAT_AC3), | 
 | 145 |     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 146 | }; | 
 | 147 |  | 
 | 148 | const StringToEnum sOutChannelsNameToEnumTable[] = { | 
 | 149 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO), | 
 | 150 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO), | 
 | 151 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), | 
 | 152 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1), | 
 | 153 | }; | 
 | 154 |  | 
 | 155 | const StringToEnum sInChannelsNameToEnumTable[] = { | 
 | 156 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO), | 
 | 157 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO), | 
 | 158 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK), | 
 | 159 | }; | 
 | 160 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 161 | const StringToEnum sGainModeNameToEnumTable[] = { | 
 | 162 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT), | 
 | 163 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS), | 
 | 164 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP), | 
 | 165 | }; | 
 | 166 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 167 |  | 
 | 168 | uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table, | 
 | 169 |                                               size_t size, | 
 | 170 |                                               const char *name) | 
 | 171 | { | 
 | 172 |     for (size_t i = 0; i < size; i++) { | 
 | 173 |         if (strcmp(table[i].name, name) == 0) { | 
 | 174 |             ALOGV("stringToEnum() found %s", table[i].name); | 
 | 175 |             return table[i].value; | 
 | 176 |         } | 
 | 177 |     } | 
 | 178 |     return 0; | 
 | 179 | } | 
 | 180 |  | 
 | 181 | const char *AudioPolicyManager::enumToString(const struct StringToEnum *table, | 
 | 182 |                                               size_t size, | 
 | 183 |                                               uint32_t value) | 
 | 184 | { | 
 | 185 |     for (size_t i = 0; i < size; i++) { | 
 | 186 |         if (table[i].value == value) { | 
 | 187 |             return table[i].name; | 
 | 188 |         } | 
 | 189 |     } | 
 | 190 |     return ""; | 
 | 191 | } | 
 | 192 |  | 
 | 193 | bool AudioPolicyManager::stringToBool(const char *value) | 
 | 194 | { | 
 | 195 |     return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0)); | 
 | 196 | } | 
 | 197 |  | 
 | 198 |  | 
 | 199 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 200 | // AudioPolicyInterface implementation | 
 | 201 | // ---------------------------------------------------------------------------- | 
 | 202 |  | 
 | 203 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 204 | status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 205 |                                                           audio_policy_dev_state_t state, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 206 |                                                   const char *device_address) | 
 | 207 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 208 |     String8 address = String8(device_address); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 209 |  | 
 | 210 |     ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address); | 
 | 211 |  | 
 | 212 |     // connect/disconnect only 1 device at a time | 
 | 213 |     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE; | 
 | 214 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 215 |     // handle output devices | 
 | 216 |     if (audio_is_output_device(device)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 217 |         SortedVector <audio_io_handle_t> outputs; | 
 | 218 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 219 |         sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 220 |         devDesc->mAddress = address; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 221 |         ssize_t index = mAvailableOutputDevices.indexOf(devDesc); | 
 | 222 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 223 |         // save a copy of the opened output descriptors before any output is opened or closed | 
 | 224 |         // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies() | 
 | 225 |         mPreviousOutputs = mOutputs; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 226 |         switch (state) | 
 | 227 |         { | 
 | 228 |         // handle output device connection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 229 |         case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 230 |             if (index >= 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 231 |                 ALOGW("setDeviceConnectionState() device already connected: %x", device); | 
 | 232 |                 return INVALID_OPERATION; | 
 | 233 |             } | 
 | 234 |             ALOGV("setDeviceConnectionState() connecting device %x", device); | 
 | 235 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 236 |             // register new device as available | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 237 |             index = mAvailableOutputDevices.add(devDesc); | 
 | 238 |             if (index >= 0) { | 
 | 239 |                 mAvailableOutputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 240 |                 sp<HwModule> module = getModuleForDevice(device); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 241 |                 ALOG_ASSERT(module != NULL, "setDeviceConnectionState():" | 
 | 242 |                         "could not find HW module for device %08x", device); | 
 | 243 |                 mAvailableOutputDevices[index]->mModule = module; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 244 |             } else { | 
 | 245 |                 return NO_MEMORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 246 |             } | 
 | 247 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 248 |             if (checkOutputsForDevice(device, state, outputs, address) != NO_ERROR) { | 
 | 249 |                 mAvailableOutputDevices.remove(devDesc); | 
 | 250 |                 return INVALID_OPERATION; | 
 | 251 |             } | 
 | 252 |             // outputs should never be empty here | 
 | 253 |             ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" | 
 | 254 |                     "checkOutputsForDevice() returned no outputs but status OK"); | 
 | 255 |             ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs", | 
 | 256 |                   outputs.size()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 257 |             break; | 
 | 258 |         // handle output device disconnection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 259 |         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 260 |             if (index < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 261 |                 ALOGW("setDeviceConnectionState() device not connected: %x", device); | 
 | 262 |                 return INVALID_OPERATION; | 
 | 263 |             } | 
 | 264 |  | 
 | 265 |             ALOGV("setDeviceConnectionState() disconnecting device %x", device); | 
 | 266 |             // remove device from available output devices | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 267 |             mAvailableOutputDevices.remove(devDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 268 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 269 |             checkOutputsForDevice(device, state, outputs, address); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 270 |             } break; | 
 | 271 |  | 
 | 272 |         default: | 
 | 273 |             ALOGE("setDeviceConnectionState() invalid state: %x", state); | 
 | 274 |             return BAD_VALUE; | 
 | 275 |         } | 
 | 276 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 277 |         // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP | 
 | 278 |         // output is suspended before any tracks are moved to it | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 279 |         checkA2dpSuspend(); | 
 | 280 |         checkOutputForAllStrategies(); | 
 | 281 |         // outputs must be closed after checkOutputForAllStrategies() is executed | 
 | 282 |         if (!outputs.isEmpty()) { | 
 | 283 |             for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 284 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 285 |                 // close unused outputs after device disconnection or direct outputs that have been | 
 | 286 |                 // opened by checkOutputsForDevice() to query dynamic parameters | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 287 |                 if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 288 |                         (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && | 
 | 289 |                          (desc->mDirectOpenCount == 0))) { | 
 | 290 |                     closeOutput(outputs[i]); | 
 | 291 |                 } | 
 | 292 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 293 |             // check again after closing A2DP output to reset mA2dpSuspended if needed | 
 | 294 |             checkA2dpSuspend(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 295 |         } | 
 | 296 |  | 
 | 297 |         updateDevicesAndOutputs(); | 
 | 298 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 299 |             // do not force device change on duplicated output because if device is 0, it will | 
 | 300 |             // also force a device 0 for the two outputs it is duplicated to which may override | 
 | 301 |             // a valid device selection on those outputs. | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 302 |             bool force = !mOutputs.valueAt(i)->isDuplicated() | 
 | 303 |                     && (!deviceDistinguishesOnAddress(device) | 
 | 304 |                             // always force when disconnecting (a non-duplicated device) | 
 | 305 |                             || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 306 |             setOutputDevice(mOutputs.keyAt(i), | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 307 |                             getNewOutputDevice(mOutputs.keyAt(i), true /*fromCache*/), | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 308 |                             force, 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 309 |         } | 
 | 310 |  | 
| Eric Laurent | 72aa32f | 2014-05-30 18:51:48 -0700 | [diff] [blame] | 311 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | b71e58b | 2014-05-29 16:08:11 -0700 | [diff] [blame] | 312 |         return NO_ERROR; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 313 |     }  // end if is output device | 
 | 314 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 315 |     // handle input devices | 
 | 316 |     if (audio_is_input_device(device)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 317 |         SortedVector <audio_io_handle_t> inputs; | 
 | 318 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 319 |         sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 320 |         devDesc->mAddress = address; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 321 |         ssize_t index = mAvailableInputDevices.indexOf(devDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 322 |         switch (state) | 
 | 323 |         { | 
 | 324 |         // handle input device connection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 325 |         case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 326 |             if (index >= 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 327 |                 ALOGW("setDeviceConnectionState() device already connected: %d", device); | 
 | 328 |                 return INVALID_OPERATION; | 
 | 329 |             } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 330 |             sp<HwModule> module = getModuleForDevice(device); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 331 |             if (module == NULL) { | 
 | 332 |                 ALOGW("setDeviceConnectionState(): could not find HW module for device %08x", | 
 | 333 |                       device); | 
 | 334 |                 return INVALID_OPERATION; | 
 | 335 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 336 |             if (checkInputsForDevice(device, state, inputs, address) != NO_ERROR) { | 
 | 337 |                 return INVALID_OPERATION; | 
 | 338 |             } | 
 | 339 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 340 |             index = mAvailableInputDevices.add(devDesc); | 
 | 341 |             if (index >= 0) { | 
 | 342 |                 mAvailableInputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 343 |                 mAvailableInputDevices[index]->mModule = module; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 344 |             } else { | 
 | 345 |                 return NO_MEMORY; | 
 | 346 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 347 |         } break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 348 |  | 
 | 349 |         // handle input device disconnection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 350 |         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 351 |             if (index < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 352 |                 ALOGW("setDeviceConnectionState() device not connected: %d", device); | 
 | 353 |                 return INVALID_OPERATION; | 
 | 354 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 355 |             checkInputsForDevice(device, state, inputs, address); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 356 |             mAvailableInputDevices.remove(devDesc); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 357 |         } break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 358 |  | 
 | 359 |         default: | 
 | 360 |             ALOGE("setDeviceConnectionState() invalid state: %x", state); | 
 | 361 |             return BAD_VALUE; | 
 | 362 |         } | 
 | 363 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 364 |         closeAllInputs(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 365 |  | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 366 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 367 |         return NO_ERROR; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 368 |     } // end if is input device | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 369 |  | 
 | 370 |     ALOGW("setDeviceConnectionState() invalid device: %x", device); | 
 | 371 |     return BAD_VALUE; | 
 | 372 | } | 
 | 373 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 374 | audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 375 |                                                   const char *device_address) | 
 | 376 | { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 377 |     audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 378 |     String8 address = String8(device_address); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 379 |     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 380 |     devDesc->mAddress = String8(device_address); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 381 |     ssize_t index; | 
 | 382 |     DeviceVector *deviceVector; | 
 | 383 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 384 |     if (audio_is_output_device(device)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 385 |         deviceVector = &mAvailableOutputDevices; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 386 |     } else if (audio_is_input_device(device)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 387 |         deviceVector = &mAvailableInputDevices; | 
 | 388 |     } else { | 
 | 389 |         ALOGW("getDeviceConnectionState() invalid device type %08x", device); | 
 | 390 |         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 391 |     } | 
 | 392 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 393 |     index = deviceVector->indexOf(devDesc); | 
 | 394 |     if (index >= 0) { | 
 | 395 |         return AUDIO_POLICY_DEVICE_STATE_AVAILABLE; | 
 | 396 |     } else { | 
 | 397 |         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
 | 398 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 399 | } | 
 | 400 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 401 | void AudioPolicyManager::setPhoneState(audio_mode_t state) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 402 | { | 
 | 403 |     ALOGV("setPhoneState() state %d", state); | 
 | 404 |     audio_devices_t newDevice = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 405 |     if (state < 0 || state >= AUDIO_MODE_CNT) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 406 |         ALOGW("setPhoneState() invalid state %d", state); | 
 | 407 |         return; | 
 | 408 |     } | 
 | 409 |  | 
 | 410 |     if (state == mPhoneState ) { | 
 | 411 |         ALOGW("setPhoneState() setting same state %d", state); | 
 | 412 |         return; | 
 | 413 |     } | 
 | 414 |  | 
 | 415 |     // if leaving call state, handle special case of active streams | 
 | 416 |     // pertaining to sonification strategy see handleIncallSonification() | 
 | 417 |     if (isInCall()) { | 
 | 418 |         ALOGV("setPhoneState() in call state management: new state is %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 419 |         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 420 |             handleIncallSonification((audio_stream_type_t)stream, false, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 421 |         } | 
 | 422 |     } | 
 | 423 |  | 
 | 424 |     // store previous phone state for management of sonification strategy below | 
 | 425 |     int oldState = mPhoneState; | 
 | 426 |     mPhoneState = state; | 
 | 427 |     bool force = false; | 
 | 428 |  | 
 | 429 |     // are we entering or starting a call | 
 | 430 |     if (!isStateInCall(oldState) && isStateInCall(state)) { | 
 | 431 |         ALOGV("  Entering call in setPhoneState()"); | 
 | 432 |         // force routing command to audio hardware when starting a call | 
 | 433 |         // even if no device change is needed | 
 | 434 |         force = true; | 
 | 435 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 436 |             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = | 
 | 437 |                     sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]; | 
 | 438 |         } | 
 | 439 |     } else if (isStateInCall(oldState) && !isStateInCall(state)) { | 
 | 440 |         ALOGV("  Exiting call in setPhoneState()"); | 
 | 441 |         // force routing command to audio hardware when exiting a call | 
 | 442 |         // even if no device change is needed | 
 | 443 |         force = true; | 
 | 444 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 445 |             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = | 
 | 446 |                     sVolumeProfiles[AUDIO_STREAM_DTMF][j]; | 
 | 447 |         } | 
 | 448 |     } else if (isStateInCall(state) && (state != oldState)) { | 
 | 449 |         ALOGV("  Switching between telephony and VoIP in setPhoneState()"); | 
 | 450 |         // force routing command to audio hardware when switching between telephony and VoIP | 
 | 451 |         // even if no device change is needed | 
 | 452 |         force = true; | 
 | 453 |     } | 
 | 454 |  | 
 | 455 |     // check for device and output changes triggered by new phone state | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 456 |     newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 457 |     checkA2dpSuspend(); | 
 | 458 |     checkOutputForAllStrategies(); | 
 | 459 |     updateDevicesAndOutputs(); | 
 | 460 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 461 |     sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 462 |  | 
 | 463 |     // force routing command to audio hardware when ending call | 
 | 464 |     // even if no device change is needed | 
 | 465 |     if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { | 
 | 466 |         newDevice = hwOutputDesc->device(); | 
 | 467 |     } | 
 | 468 |  | 
 | 469 |     int delayMs = 0; | 
 | 470 |     if (isStateInCall(state)) { | 
 | 471 |         nsecs_t sysTime = systemTime(); | 
 | 472 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 473 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 474 |             // mute media and sonification strategies and delay device switch by the largest | 
 | 475 |             // latency of any output where either strategy is active. | 
 | 476 |             // This avoid sending the ring tone or music tail into the earpiece or headset. | 
 | 477 |             if ((desc->isStrategyActive(STRATEGY_MEDIA, | 
 | 478 |                                      SONIFICATION_HEADSET_MUSIC_DELAY, | 
 | 479 |                                      sysTime) || | 
 | 480 |                     desc->isStrategyActive(STRATEGY_SONIFICATION, | 
 | 481 |                                          SONIFICATION_HEADSET_MUSIC_DELAY, | 
 | 482 |                                          sysTime)) && | 
 | 483 |                     (delayMs < (int)desc->mLatency*2)) { | 
 | 484 |                 delayMs = desc->mLatency*2; | 
 | 485 |             } | 
 | 486 |             setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); | 
 | 487 |             setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, | 
 | 488 |                 getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); | 
 | 489 |             setStrategyMute(STRATEGY_SONIFICATION, true, mOutputs.keyAt(i)); | 
 | 490 |             setStrategyMute(STRATEGY_SONIFICATION, false, mOutputs.keyAt(i), MUTE_TIME_MS, | 
 | 491 |                 getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/)); | 
 | 492 |         } | 
 | 493 |     } | 
 | 494 |  | 
 | 495 |     // change routing is necessary | 
 | 496 |     setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); | 
 | 497 |  | 
 | 498 |     // if entering in call state, handle special case of active streams | 
 | 499 |     // pertaining to sonification strategy see handleIncallSonification() | 
 | 500 |     if (isStateInCall(state)) { | 
 | 501 |         ALOGV("setPhoneState() in call state management: new state is %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 502 |         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 503 |             handleIncallSonification((audio_stream_type_t)stream, true, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 504 |         } | 
 | 505 |     } | 
 | 506 |  | 
 | 507 |     // 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] | 508 |     if (state == AUDIO_MODE_RINGTONE && | 
 | 509 |         isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 510 |         mLimitRingtoneVolume = true; | 
 | 511 |     } else { | 
 | 512 |         mLimitRingtoneVolume = false; | 
 | 513 |     } | 
 | 514 | } | 
 | 515 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 516 | void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 517 |                                          audio_policy_forced_cfg_t config) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 518 | { | 
 | 519 |     ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState); | 
 | 520 |  | 
 | 521 |     bool forceVolumeReeval = false; | 
 | 522 |     switch(usage) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 523 |     case AUDIO_POLICY_FORCE_FOR_COMMUNICATION: | 
 | 524 |         if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO && | 
 | 525 |             config != AUDIO_POLICY_FORCE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 526 |             ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config); | 
 | 527 |             return; | 
 | 528 |         } | 
 | 529 |         forceVolumeReeval = true; | 
 | 530 |         mForceUse[usage] = config; | 
 | 531 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 532 |     case AUDIO_POLICY_FORCE_FOR_MEDIA: | 
 | 533 |         if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP && | 
 | 534 |             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 535 |             config != AUDIO_POLICY_FORCE_ANALOG_DOCK && | 
 | 536 |             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE && | 
| Jungshik Jang | 0c94309 | 2014-07-08 22:11:24 +0900 | [diff] [blame] | 537 |             config != AUDIO_POLICY_FORCE_NO_BT_A2DP) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 538 |             ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config); | 
 | 539 |             return; | 
 | 540 |         } | 
 | 541 |         mForceUse[usage] = config; | 
 | 542 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 543 |     case AUDIO_POLICY_FORCE_FOR_RECORD: | 
 | 544 |         if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 545 |             config != AUDIO_POLICY_FORCE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 546 |             ALOGW("setForceUse() invalid config %d for FOR_RECORD", config); | 
 | 547 |             return; | 
 | 548 |         } | 
 | 549 |         mForceUse[usage] = config; | 
 | 550 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 551 |     case AUDIO_POLICY_FORCE_FOR_DOCK: | 
 | 552 |         if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK && | 
 | 553 |             config != AUDIO_POLICY_FORCE_BT_DESK_DOCK && | 
 | 554 |             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 555 |             config != AUDIO_POLICY_FORCE_ANALOG_DOCK && | 
 | 556 |             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 557 |             ALOGW("setForceUse() invalid config %d for FOR_DOCK", config); | 
 | 558 |         } | 
 | 559 |         forceVolumeReeval = true; | 
 | 560 |         mForceUse[usage] = config; | 
 | 561 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 562 |     case AUDIO_POLICY_FORCE_FOR_SYSTEM: | 
 | 563 |         if (config != AUDIO_POLICY_FORCE_NONE && | 
 | 564 |             config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 565 |             ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config); | 
 | 566 |         } | 
 | 567 |         forceVolumeReeval = true; | 
 | 568 |         mForceUse[usage] = config; | 
 | 569 |         break; | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 570 |     case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO: | 
 | 571 |         if (config != AUDIO_POLICY_FORCE_NONE && | 
 | 572 |             config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) { | 
 | 573 |             ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config); | 
 | 574 |         } | 
 | 575 |         mForceUse[usage] = config; | 
 | 576 |         break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 577 |     default: | 
 | 578 |         ALOGW("setForceUse() invalid usage %d", usage); | 
 | 579 |         break; | 
 | 580 |     } | 
 | 581 |  | 
 | 582 |     // check for device and output changes triggered by new force usage | 
 | 583 |     checkA2dpSuspend(); | 
 | 584 |     checkOutputForAllStrategies(); | 
 | 585 |     updateDevicesAndOutputs(); | 
 | 586 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 587 |         audio_io_handle_t output = mOutputs.keyAt(i); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 588 |         audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 589 |         setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE)); | 
 | 590 |         if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) { | 
 | 591 |             applyStreamVolumes(output, newDevice, 0, true); | 
 | 592 |         } | 
 | 593 |     } | 
 | 594 |  | 
 | 595 |     audio_io_handle_t activeInput = getActiveInput(); | 
 | 596 |     if (activeInput != 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 597 |         setInputDevice(activeInput, getNewInputDevice(activeInput)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 598 |     } | 
 | 599 |  | 
 | 600 | } | 
 | 601 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 602 | 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] | 603 | { | 
 | 604 |     return mForceUse[usage]; | 
 | 605 | } | 
 | 606 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 607 | void AudioPolicyManager::setSystemProperty(const char* property, const char* value) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 608 | { | 
 | 609 |     ALOGV("setSystemProperty() property %s, value %s", property, value); | 
 | 610 | } | 
 | 611 |  | 
 | 612 | // Find a direct output profile compatible with the parameters passed, even if the input flags do | 
 | 613 | // not explicitly request a direct output | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 614 | sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getProfileForDirectOutput( | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 615 |                                                                audio_devices_t device, | 
 | 616 |                                                                uint32_t samplingRate, | 
 | 617 |                                                                audio_format_t format, | 
 | 618 |                                                                audio_channel_mask_t channelMask, | 
 | 619 |                                                                audio_output_flags_t flags) | 
 | 620 | { | 
 | 621 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 622 |         if (mHwModules[i]->mHandle == 0) { | 
 | 623 |             continue; | 
 | 624 |         } | 
 | 625 |         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 626 |             sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 627 |             bool found = profile->isCompatibleProfile(device, samplingRate, | 
 | 628 |                     NULL /*updatedSamplingRate*/, format, channelMask, | 
 | 629 |                     flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ? | 
 | 630 |                         AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_DIRECT); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 631 |             if (found && (mAvailableOutputDevices.types() & profile->mSupportedDevices.types())) { | 
 | 632 |                 return profile; | 
 | 633 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 634 |         } | 
 | 635 |     } | 
 | 636 |     return 0; | 
 | 637 | } | 
 | 638 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 639 | audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 640 |                                     uint32_t samplingRate, | 
 | 641 |                                     audio_format_t format, | 
 | 642 |                                     audio_channel_mask_t channelMask, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 643 |                                     audio_output_flags_t flags, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 644 |                                     const audio_offload_info_t *offloadInfo) | 
 | 645 | { | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 646 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 647 |     routing_strategy strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 648 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 649 |     ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x", | 
 | 650 |           device, stream, samplingRate, format, channelMask, flags); | 
 | 651 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 652 |     return getOutputForDevice(device, stream, samplingRate,format, channelMask, flags, | 
 | 653 |             offloadInfo); | 
 | 654 | } | 
 | 655 |  | 
 | 656 | audio_io_handle_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, | 
 | 657 |                                     uint32_t samplingRate, | 
 | 658 |                                     audio_format_t format, | 
 | 659 |                                     audio_channel_mask_t channelMask, | 
 | 660 |                                     audio_output_flags_t flags, | 
 | 661 |                                     const audio_offload_info_t *offloadInfo) | 
 | 662 | { | 
 | 663 |     if (attr == NULL) { | 
 | 664 |         ALOGE("getOutputForAttr() called with NULL audio attributes"); | 
 | 665 |         return 0; | 
 | 666 |     } | 
 | 667 |     ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s", | 
 | 668 |             attr->usage, attr->content_type, attr->tags); | 
 | 669 |  | 
 | 670 |     // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go | 
 | 671 |     routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr); | 
 | 672 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 673 |     ALOGV("getOutputForAttr() device %d, samplingRate %d, format %x, channelMask %x, flags %x", | 
 | 674 |           device, samplingRate, format, channelMask, flags); | 
 | 675 |  | 
 | 676 |     audio_stream_type_t stream = streamTypefromAttributesInt(attr); | 
 | 677 |     return getOutputForDevice(device, stream, samplingRate, format, channelMask, flags, | 
 | 678 |                 offloadInfo); | 
 | 679 | } | 
 | 680 |  | 
 | 681 | audio_io_handle_t AudioPolicyManager::getOutputForDevice( | 
 | 682 |         audio_devices_t device, | 
 | 683 |         audio_stream_type_t stream, | 
 | 684 |         uint32_t samplingRate, | 
 | 685 |         audio_format_t format, | 
 | 686 |         audio_channel_mask_t channelMask, | 
 | 687 |         audio_output_flags_t flags, | 
 | 688 |         const audio_offload_info_t *offloadInfo) | 
 | 689 | { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 690 |     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 691 |     uint32_t latency = 0; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 692 |     status_t status; | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 693 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 694 | #ifdef AUDIO_POLICY_TEST | 
 | 695 |     if (mCurOutput != 0) { | 
 | 696 |         ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d", | 
 | 697 |                 mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput); | 
 | 698 |  | 
 | 699 |         if (mTestOutputs[mCurOutput] == 0) { | 
 | 700 |             ALOGV("getOutput() opening test output"); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 701 |             sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 702 |             outputDesc->mDevice = mTestDevice; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 703 |             outputDesc->mLatency = mTestLatencyMs; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 704 |             outputDesc->mFlags = | 
 | 705 |                     (audio_output_flags_t)(mDirectOutput ? AUDIO_OUTPUT_FLAG_DIRECT : 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 706 |             outputDesc->mRefCount[stream] = 0; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 707 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 708 |             config.sample_rate = mTestSamplingRate; | 
 | 709 |             config.channel_mask = mTestChannels; | 
 | 710 |             config.format = mTestFormat; | 
 | 711 |             config.offload_info = *offloadInfo; | 
 | 712 |             status = mpClientInterface->openOutput(0, | 
 | 713 |                                                   &mTestOutputs[mCurOutput], | 
 | 714 |                                                   &config, | 
 | 715 |                                                   &outputDesc->mDevice, | 
 | 716 |                                                   String8(""), | 
 | 717 |                                                   &outputDesc->mLatency, | 
 | 718 |                                                   outputDesc->mFlags); | 
 | 719 |             if (status == NO_ERROR) { | 
 | 720 |                 outputDesc->mSamplingRate = config.sample_rate; | 
 | 721 |                 outputDesc->mFormat = config.format; | 
 | 722 |                 outputDesc->mChannelMask = config.channel_mask; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 723 |                 AudioParameter outputCmd = AudioParameter(); | 
 | 724 |                 outputCmd.addInt(String8("set_id"),mCurOutput); | 
 | 725 |                 mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString()); | 
 | 726 |                 addOutput(mTestOutputs[mCurOutput], outputDesc); | 
 | 727 |             } | 
 | 728 |         } | 
 | 729 |         return mTestOutputs[mCurOutput]; | 
 | 730 |     } | 
 | 731 | #endif //AUDIO_POLICY_TEST | 
 | 732 |  | 
 | 733 |     // open a direct output if required by specified parameters | 
 | 734 |     //force direct flag if offload flag is set: offloading implies a direct output stream | 
 | 735 |     // and all common behaviors are driven by checking only the direct flag | 
 | 736 |     // this should normally be set appropriately in the policy configuration file | 
 | 737 |     if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 738 |         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 739 |     } | 
 | 740 |  | 
 | 741 |     // Do not allow offloading if one non offloadable effect is enabled. This prevents from | 
 | 742 |     // creating an offloaded track and tearing it down immediately after start when audioflinger | 
 | 743 |     // detects there is an active non offloadable effect. | 
 | 744 |     // FIXME: We should check the audio session here but we do not have it in this context. | 
 | 745 |     // This may prevent offloading in rare situations where effects are left active by apps | 
 | 746 |     // in the background. | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 747 |     sp<IOProfile> profile; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 748 |     if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || | 
 | 749 |             !isNonOffloadableEffectEnabled()) { | 
 | 750 |         profile = getProfileForDirectOutput(device, | 
 | 751 |                                            samplingRate, | 
 | 752 |                                            format, | 
 | 753 |                                            channelMask, | 
 | 754 |                                            (audio_output_flags_t)flags); | 
 | 755 |     } | 
 | 756 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 757 |     if (profile != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 758 |         sp<AudioOutputDescriptor> outputDesc = NULL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 759 |  | 
 | 760 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 761 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 762 |             if (!desc->isDuplicated() && (profile == desc->mProfile)) { | 
 | 763 |                 outputDesc = desc; | 
 | 764 |                 // reuse direct output if currently open and configured with same parameters | 
 | 765 |                 if ((samplingRate == outputDesc->mSamplingRate) && | 
 | 766 |                         (format == outputDesc->mFormat) && | 
 | 767 |                         (channelMask == outputDesc->mChannelMask)) { | 
 | 768 |                     outputDesc->mDirectOpenCount++; | 
 | 769 |                     ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i)); | 
 | 770 |                     return mOutputs.keyAt(i); | 
 | 771 |                 } | 
 | 772 |             } | 
 | 773 |         } | 
 | 774 |         // close direct output if currently open and configured with different parameters | 
 | 775 |         if (outputDesc != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 776 |             closeOutput(outputDesc->mIoHandle); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 777 |         } | 
 | 778 |         outputDesc = new AudioOutputDescriptor(profile); | 
 | 779 |         outputDesc->mDevice = device; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 780 |         outputDesc->mLatency = 0; | 
 | 781 |         outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 782 |         audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 783 |         config.sample_rate = samplingRate; | 
 | 784 |         config.channel_mask = channelMask; | 
 | 785 |         config.format = format; | 
 | 786 |         config.offload_info = *offloadInfo; | 
 | 787 |         status = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 788 |                                                &output, | 
 | 789 |                                                &config, | 
 | 790 |                                                &outputDesc->mDevice, | 
 | 791 |                                                String8(""), | 
 | 792 |                                                &outputDesc->mLatency, | 
 | 793 |                                                outputDesc->mFlags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 794 |  | 
 | 795 |         // only accept an output with the requested parameters | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 796 |         if (status != NO_ERROR || | 
 | 797 |             (samplingRate != 0 && samplingRate != config.sample_rate) || | 
 | 798 |             (format != AUDIO_FORMAT_DEFAULT && format != config.format) || | 
 | 799 |             (channelMask != 0 && channelMask != config.channel_mask)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 800 |             ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d," | 
 | 801 |                     "format %d %d, channelMask %04x %04x", output, samplingRate, | 
 | 802 |                     outputDesc->mSamplingRate, format, outputDesc->mFormat, channelMask, | 
 | 803 |                     outputDesc->mChannelMask); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 804 |             if (output != AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 805 |                 mpClientInterface->closeOutput(output); | 
 | 806 |             } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 807 |             return AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 808 |         } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 809 |         outputDesc->mSamplingRate = config.sample_rate; | 
 | 810 |         outputDesc->mChannelMask = config.channel_mask; | 
 | 811 |         outputDesc->mFormat = config.format; | 
 | 812 |         outputDesc->mRefCount[stream] = 0; | 
 | 813 |         outputDesc->mStopTime[stream] = 0; | 
 | 814 |         outputDesc->mDirectOpenCount = 1; | 
 | 815 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 816 |         audio_io_handle_t srcOutput = getOutputForEffect(); | 
 | 817 |         addOutput(output, outputDesc); | 
 | 818 |         audio_io_handle_t dstOutput = getOutputForEffect(); | 
 | 819 |         if (dstOutput == output) { | 
 | 820 |             mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput); | 
 | 821 |         } | 
 | 822 |         mPreviousOutputs = mOutputs; | 
 | 823 |         ALOGV("getOutput() returns new direct output %d", output); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 824 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 825 |         return output; | 
 | 826 |     } | 
 | 827 |  | 
 | 828 |     // ignoring channel mask due to downmix capability in mixer | 
 | 829 |  | 
 | 830 |     // open a non direct output | 
 | 831 |  | 
 | 832 |     // for non direct outputs, only PCM is supported | 
 | 833 |     if (audio_is_linear_pcm(format)) { | 
 | 834 |         // get which output is suitable for the specified stream. The actual | 
 | 835 |         // routing change will happen when startOutput() will be called | 
 | 836 |         SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); | 
 | 837 |  | 
 | 838 |         output = selectOutput(outputs, flags); | 
 | 839 |     } | 
 | 840 |     ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d," | 
 | 841 |             "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags); | 
 | 842 |  | 
 | 843 |     ALOGV("getOutput() returns output %d", output); | 
 | 844 |  | 
 | 845 |     return output; | 
 | 846 | } | 
 | 847 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 848 | audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 849 |                                                        audio_output_flags_t flags) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 850 | { | 
 | 851 |     // select one output among several that provide a path to a particular device or set of | 
 | 852 |     // devices (the list was previously build by getOutputsForDevice()). | 
 | 853 |     // The priority is as follows: | 
 | 854 |     // 1: the output with the highest number of requested policy flags | 
 | 855 |     // 2: the primary output | 
 | 856 |     // 3: the first output in the list | 
 | 857 |  | 
 | 858 |     if (outputs.size() == 0) { | 
 | 859 |         return 0; | 
 | 860 |     } | 
 | 861 |     if (outputs.size() == 1) { | 
 | 862 |         return outputs[0]; | 
 | 863 |     } | 
 | 864 |  | 
 | 865 |     int maxCommonFlags = 0; | 
 | 866 |     audio_io_handle_t outputFlags = 0; | 
 | 867 |     audio_io_handle_t outputPrimary = 0; | 
 | 868 |  | 
 | 869 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 870 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 871 |         if (!outputDesc->isDuplicated()) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 872 |             int commonFlags = popcount(outputDesc->mProfile->mFlags & flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 873 |             if (commonFlags > maxCommonFlags) { | 
 | 874 |                 outputFlags = outputs[i]; | 
 | 875 |                 maxCommonFlags = commonFlags; | 
 | 876 |                 ALOGV("selectOutput() commonFlags for output %d, %04x", outputs[i], commonFlags); | 
 | 877 |             } | 
 | 878 |             if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { | 
 | 879 |                 outputPrimary = outputs[i]; | 
 | 880 |             } | 
 | 881 |         } | 
 | 882 |     } | 
 | 883 |  | 
 | 884 |     if (outputFlags != 0) { | 
 | 885 |         return outputFlags; | 
 | 886 |     } | 
 | 887 |     if (outputPrimary != 0) { | 
 | 888 |         return outputPrimary; | 
 | 889 |     } | 
 | 890 |  | 
 | 891 |     return outputs[0]; | 
 | 892 | } | 
 | 893 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 894 | status_t AudioPolicyManager::startOutput(audio_io_handle_t output, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 895 |                                              audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 896 |                                              int session) | 
 | 897 | { | 
 | 898 |     ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session); | 
 | 899 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 900 |     if (index < 0) { | 
 | 901 |         ALOGW("startOutput() unknown output %d", output); | 
 | 902 |         return BAD_VALUE; | 
 | 903 |     } | 
 | 904 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 905 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 906 |  | 
 | 907 |     // increment usage count for this stream on the requested output: | 
 | 908 |     // NOTE that the usage count is the same for duplicated output and hardware output which is | 
 | 909 |     // necessary for a correct control of hardware output routing by startOutput() and stopOutput() | 
 | 910 |     outputDesc->changeRefCount(stream, 1); | 
 | 911 |  | 
 | 912 |     if (outputDesc->mRefCount[stream] == 1) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 913 |         audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 914 |         routing_strategy strategy = getStrategy(stream); | 
 | 915 |         bool shouldWait = (strategy == STRATEGY_SONIFICATION) || | 
 | 916 |                             (strategy == STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 917 |         uint32_t waitMs = 0; | 
 | 918 |         bool force = false; | 
 | 919 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 920 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 921 |             if (desc != outputDesc) { | 
 | 922 |                 // force a device change if any other output is managed by the same hw | 
 | 923 |                 // module and has a current device selection that differs from selected device. | 
 | 924 |                 // In this case, the audio HAL must receive the new device selection so that it can | 
 | 925 |                 // change the device currently selected by the other active output. | 
 | 926 |                 if (outputDesc->sharesHwModuleWith(desc) && | 
 | 927 |                     desc->device() != newDevice) { | 
 | 928 |                     force = true; | 
 | 929 |                 } | 
 | 930 |                 // wait for audio on other active outputs to be presented when starting | 
 | 931 |                 // a notification so that audio focus effect can propagate. | 
 | 932 |                 uint32_t latency = desc->latency(); | 
 | 933 |                 if (shouldWait && desc->isActive(latency * 2) && (waitMs < latency)) { | 
 | 934 |                     waitMs = latency; | 
 | 935 |                 } | 
 | 936 |             } | 
 | 937 |         } | 
 | 938 |         uint32_t muteWaitMs = setOutputDevice(output, newDevice, force); | 
 | 939 |  | 
 | 940 |         // handle special case for sonification while in call | 
 | 941 |         if (isInCall()) { | 
 | 942 |             handleIncallSonification(stream, true, false); | 
 | 943 |         } | 
 | 944 |  | 
 | 945 |         // apply volume rules for current stream and device if necessary | 
 | 946 |         checkAndSetVolume(stream, | 
 | 947 |                           mStreams[stream].getVolumeIndex(newDevice), | 
 | 948 |                           output, | 
 | 949 |                           newDevice); | 
 | 950 |  | 
 | 951 |         // update the outputs if starting an output with a stream that can affect notification | 
 | 952 |         // routing | 
 | 953 |         handleNotificationRoutingForStream(stream); | 
 | 954 |         if (waitMs > muteWaitMs) { | 
 | 955 |             usleep((waitMs - muteWaitMs) * 2 * 1000); | 
 | 956 |         } | 
 | 957 |     } | 
 | 958 |     return NO_ERROR; | 
 | 959 | } | 
 | 960 |  | 
 | 961 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 962 | status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 963 |                                             audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 964 |                                             int session) | 
 | 965 | { | 
 | 966 |     ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session); | 
 | 967 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 968 |     if (index < 0) { | 
 | 969 |         ALOGW("stopOutput() unknown output %d", output); | 
 | 970 |         return BAD_VALUE; | 
 | 971 |     } | 
 | 972 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 973 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 974 |  | 
 | 975 |     // handle special case for sonification while in call | 
 | 976 |     if (isInCall()) { | 
 | 977 |         handleIncallSonification(stream, false, false); | 
 | 978 |     } | 
 | 979 |  | 
 | 980 |     if (outputDesc->mRefCount[stream] > 0) { | 
 | 981 |         // decrement usage count of this stream on the output | 
 | 982 |         outputDesc->changeRefCount(stream, -1); | 
 | 983 |         // store time at which the stream was stopped - see isStreamActive() | 
 | 984 |         if (outputDesc->mRefCount[stream] == 0) { | 
 | 985 |             outputDesc->mStopTime[stream] = systemTime(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 986 |             audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 987 |             // delay the device switch by twice the latency because stopOutput() is executed when | 
 | 988 |             // the track stop() command is received and at that time the audio track buffer can | 
 | 989 |             // still contain data that needs to be drained. The latency only covers the audio HAL | 
 | 990 |             // and kernel buffers. Also the latency does not always include additional delay in the | 
 | 991 |             // audio path (audio DSP, CODEC ...) | 
 | 992 |             setOutputDevice(output, newDevice, false, outputDesc->mLatency*2); | 
 | 993 |  | 
 | 994 |             // force restoring the device selection on other active outputs if it differs from the | 
 | 995 |             // one being selected for this output | 
 | 996 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 997 |                 audio_io_handle_t curOutput = mOutputs.keyAt(i); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 998 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 999 |                 if (curOutput != output && | 
 | 1000 |                         desc->isActive() && | 
 | 1001 |                         outputDesc->sharesHwModuleWith(desc) && | 
 | 1002 |                         (newDevice != desc->device())) { | 
 | 1003 |                     setOutputDevice(curOutput, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1004 |                                     getNewOutputDevice(curOutput, false /*fromCache*/), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1005 |                                     true, | 
 | 1006 |                                     outputDesc->mLatency*2); | 
 | 1007 |                 } | 
 | 1008 |             } | 
 | 1009 |             // update the outputs if stopping one with a stream that can affect notification routing | 
 | 1010 |             handleNotificationRoutingForStream(stream); | 
 | 1011 |         } | 
 | 1012 |         return NO_ERROR; | 
 | 1013 |     } else { | 
 | 1014 |         ALOGW("stopOutput() refcount is already 0 for output %d", output); | 
 | 1015 |         return INVALID_OPERATION; | 
 | 1016 |     } | 
 | 1017 | } | 
 | 1018 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1019 | void AudioPolicyManager::releaseOutput(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1020 | { | 
 | 1021 |     ALOGV("releaseOutput() %d", output); | 
 | 1022 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 1023 |     if (index < 0) { | 
 | 1024 |         ALOGW("releaseOutput() releasing unknown output %d", output); | 
 | 1025 |         return; | 
 | 1026 |     } | 
 | 1027 |  | 
 | 1028 | #ifdef AUDIO_POLICY_TEST | 
 | 1029 |     int testIndex = testOutputIndex(output); | 
 | 1030 |     if (testIndex != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1031 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1032 |         if (outputDesc->isActive()) { | 
 | 1033 |             mpClientInterface->closeOutput(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1034 |             mOutputs.removeItem(output); | 
 | 1035 |             mTestOutputs[testIndex] = 0; | 
 | 1036 |         } | 
 | 1037 |         return; | 
 | 1038 |     } | 
 | 1039 | #endif //AUDIO_POLICY_TEST | 
 | 1040 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1041 |     sp<AudioOutputDescriptor> desc = mOutputs.valueAt(index); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1042 |     if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1043 |         if (desc->mDirectOpenCount <= 0) { | 
 | 1044 |             ALOGW("releaseOutput() invalid open count %d for output %d", | 
 | 1045 |                                                               desc->mDirectOpenCount, output); | 
 | 1046 |             return; | 
 | 1047 |         } | 
 | 1048 |         if (--desc->mDirectOpenCount == 0) { | 
 | 1049 |             closeOutput(output); | 
 | 1050 |             // If effects where present on the output, audioflinger moved them to the primary | 
 | 1051 |             // output by default: move them back to the appropriate output. | 
 | 1052 |             audio_io_handle_t dstOutput = getOutputForEffect(); | 
 | 1053 |             if (dstOutput != mPrimaryOutput) { | 
 | 1054 |                 mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput); | 
 | 1055 |             } | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1056 |             mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1057 |         } | 
 | 1058 |     } | 
 | 1059 | } | 
 | 1060 |  | 
 | 1061 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1062 | audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1063 |                                     uint32_t samplingRate, | 
 | 1064 |                                     audio_format_t format, | 
 | 1065 |                                     audio_channel_mask_t channelMask, | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1066 |                                     audio_session_t session, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1067 |                                     audio_input_flags_t flags) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1068 | { | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1069 |     ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, session %d, " | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1070 |           "flags %#x", | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1071 |           inputSource, samplingRate, format, channelMask, session, flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1072 |  | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1073 |     audio_devices_t device = getDeviceForInputSource(inputSource); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1074 |  | 
 | 1075 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 1076 |         ALOGW("getInput() could not find device for inputSource %d", inputSource); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1077 |         return AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1078 |     } | 
 | 1079 |  | 
 | 1080 |     // adapt channel selection to input source | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1081 |     switch (inputSource) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1082 |     case AUDIO_SOURCE_VOICE_UPLINK: | 
 | 1083 |         channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK; | 
 | 1084 |         break; | 
 | 1085 |     case AUDIO_SOURCE_VOICE_DOWNLINK: | 
 | 1086 |         channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK; | 
 | 1087 |         break; | 
 | 1088 |     case AUDIO_SOURCE_VOICE_CALL: | 
 | 1089 |         channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK; | 
 | 1090 |         break; | 
 | 1091 |     default: | 
 | 1092 |         break; | 
 | 1093 |     } | 
 | 1094 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1095 |     sp<IOProfile> profile = getInputProfile(device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1096 |                                          samplingRate, | 
 | 1097 |                                          format, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1098 |                                          channelMask, | 
 | 1099 |                                          flags); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1100 |     if (profile == 0) { | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1101 |         ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, " | 
 | 1102 |                 "channelMask 0x%X, flags %#x", | 
 | 1103 |                 device, samplingRate, format, channelMask, flags); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1104 |         return AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1105 |     } | 
 | 1106 |  | 
 | 1107 |     if (profile->mModule->mHandle == 0) { | 
 | 1108 |         ALOGE("getInput(): HW module %s not opened", profile->mModule->mName); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1109 |         return AUDIO_IO_HANDLE_NONE; | 
 | 1110 |     } | 
 | 1111 |  | 
 | 1112 |     audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 1113 |     config.sample_rate = samplingRate; | 
 | 1114 |     config.channel_mask = channelMask; | 
 | 1115 |     config.format = format; | 
 | 1116 |     audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; | 
 | 1117 |     status_t status = mpClientInterface->openInput(profile->mModule->mHandle, | 
 | 1118 |                                                    &input, | 
 | 1119 |                                                    &config, | 
 | 1120 |                                                    &device, | 
 | 1121 |                                                    String8(""), | 
 | 1122 |                                                    inputSource, | 
 | 1123 |                                                    flags); | 
 | 1124 |  | 
 | 1125 |     // only accept input with the exact requested set of parameters | 
 | 1126 |     if (status != NO_ERROR || | 
 | 1127 |         (samplingRate != config.sample_rate) || | 
 | 1128 |         (format != config.format) || | 
 | 1129 |         (channelMask != config.channel_mask)) { | 
 | 1130 |         ALOGW("getInput() failed opening input: samplingRate %d, format %d, channelMask %x", | 
 | 1131 |                 samplingRate, format, channelMask); | 
 | 1132 |         if (input != AUDIO_IO_HANDLE_NONE) { | 
 | 1133 |             mpClientInterface->closeInput(input); | 
 | 1134 |         } | 
 | 1135 |         return AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1136 |     } | 
 | 1137 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1138 |     sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1139 |     inputDesc->mInputSource = inputSource; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1140 |     inputDesc->mRefCount = 0; | 
 | 1141 |     inputDesc->mOpenRefCount = 1; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1142 |     inputDesc->mSamplingRate = samplingRate; | 
 | 1143 |     inputDesc->mFormat = format; | 
 | 1144 |     inputDesc->mChannelMask = channelMask; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 1145 |     inputDesc->mDevice = device; | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1146 |     inputDesc->mSessions.add(session); | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1147 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1148 |     addInput(input, inputDesc); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1149 |     mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1150 |     return input; | 
 | 1151 | } | 
 | 1152 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1153 | status_t AudioPolicyManager::startInput(audio_io_handle_t input, | 
 | 1154 |                                         audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1155 | { | 
 | 1156 |     ALOGV("startInput() input %d", input); | 
 | 1157 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1158 |     if (index < 0) { | 
 | 1159 |         ALOGW("startInput() unknown input %d", input); | 
 | 1160 |         return BAD_VALUE; | 
 | 1161 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1162 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1163 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1164 |     index = inputDesc->mSessions.indexOf(session); | 
 | 1165 |     if (index < 0) { | 
 | 1166 |         ALOGW("startInput() unknown session %d on input %d", session, input); | 
 | 1167 |         return BAD_VALUE; | 
 | 1168 |     } | 
 | 1169 |  | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1170 |     // virtual input devices are compatible with other input devices | 
 | 1171 |     if (!isVirtualInputDevice(inputDesc->mDevice)) { | 
 | 1172 |  | 
 | 1173 |         // 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] | 1174 |         audio_io_handle_t activeInput = getActiveInput(); | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1175 |         if (activeInput != 0 && activeInput != input) { | 
 | 1176 |  | 
 | 1177 |             // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed, | 
 | 1178 |             // otherwise the active input continues and the new input cannot be started. | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1179 |             sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1180 |             if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) { | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1181 |                 ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput); | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1182 |                 stopInput(activeInput, activeDesc->mSessions.itemAt(0)); | 
 | 1183 |                 releaseInput(activeInput, activeDesc->mSessions.itemAt(0)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1184 |             } else { | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1185 |                 ALOGE("startInput(%d) failed: other input %d already started", input, activeInput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1186 |                 return INVALID_OPERATION; | 
 | 1187 |             } | 
 | 1188 |         } | 
 | 1189 |     } | 
 | 1190 |  | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1191 |     if (inputDesc->mRefCount == 0) { | 
 | 1192 |         setInputDevice(input, getNewInputDevice(input), true /* force */); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1193 |  | 
| Glenn Kasten | 74a8e25 | 2014-07-24 14:09:55 -0700 | [diff] [blame] | 1194 |         // Automatically enable the remote submix output when input is started. | 
 | 1195 |         // For remote submix (a virtual device), we open only one input per capture request. | 
 | 1196 |         if (audio_is_remote_submix_device(inputDesc->mDevice)) { | 
 | 1197 |             setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
 | 1198 |                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); | 
 | 1199 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1200 |     } | 
 | 1201 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1202 |     ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource); | 
 | 1203 |  | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1204 |     inputDesc->mRefCount++; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1205 |     return NO_ERROR; | 
 | 1206 | } | 
 | 1207 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1208 | status_t AudioPolicyManager::stopInput(audio_io_handle_t input, | 
 | 1209 |                                        audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1210 | { | 
 | 1211 |     ALOGV("stopInput() input %d", input); | 
 | 1212 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1213 |     if (index < 0) { | 
 | 1214 |         ALOGW("stopInput() unknown input %d", input); | 
 | 1215 |         return BAD_VALUE; | 
 | 1216 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1217 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1218 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1219 |     index = inputDesc->mSessions.indexOf(session); | 
 | 1220 |     if (index < 0) { | 
 | 1221 |         ALOGW("stopInput() unknown session %d on input %d", session, input); | 
 | 1222 |         return BAD_VALUE; | 
 | 1223 |     } | 
 | 1224 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1225 |     if (inputDesc->mRefCount == 0) { | 
 | 1226 |         ALOGW("stopInput() input %d already stopped", input); | 
 | 1227 |         return INVALID_OPERATION; | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1228 |     } | 
 | 1229 |  | 
 | 1230 |     inputDesc->mRefCount--; | 
 | 1231 |     if (inputDesc->mRefCount == 0) { | 
 | 1232 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1233 |         // automatically disable the remote submix output when input is stopped | 
 | 1234 |         if (audio_is_remote_submix_device(inputDesc->mDevice)) { | 
 | 1235 |             setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1236 |                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1237 |         } | 
 | 1238 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1239 |         resetInputDevice(input); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1240 |     } | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1241 |     return NO_ERROR; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1242 | } | 
 | 1243 |  | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1244 | void AudioPolicyManager::releaseInput(audio_io_handle_t input, | 
 | 1245 |                                       audio_session_t session) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1246 | { | 
 | 1247 |     ALOGV("releaseInput() %d", input); | 
 | 1248 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1249 |     if (index < 0) { | 
 | 1250 |         ALOGW("releaseInput() releasing unknown input %d", input); | 
 | 1251 |         return; | 
 | 1252 |     } | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1253 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
 | 1254 |     ALOG_ASSERT(inputDesc != 0); | 
| Eric Laurent | 4dc6806 | 2014-07-28 17:26:49 -0700 | [diff] [blame] | 1255 |  | 
 | 1256 |     index = inputDesc->mSessions.indexOf(session); | 
 | 1257 |     if (index < 0) { | 
 | 1258 |         ALOGW("releaseInput() unknown session %d on input %d", session, input); | 
 | 1259 |         return; | 
 | 1260 |     } | 
 | 1261 |     inputDesc->mSessions.remove(session); | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1262 |     if (inputDesc->mOpenRefCount == 0) { | 
 | 1263 |         ALOGW("releaseInput() invalid open ref count %d", inputDesc->mOpenRefCount); | 
 | 1264 |         return; | 
 | 1265 |     } | 
 | 1266 |     inputDesc->mOpenRefCount--; | 
 | 1267 |     if (inputDesc->mOpenRefCount > 0) { | 
 | 1268 |         ALOGV("releaseInput() exit > 0"); | 
 | 1269 |         return; | 
 | 1270 |     } | 
 | 1271 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1272 |     mpClientInterface->closeInput(input); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1273 |     mInputs.removeItem(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1274 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1275 |     mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1276 |     ALOGV("releaseInput() exit"); | 
 | 1277 | } | 
 | 1278 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1279 | void AudioPolicyManager::closeAllInputs() { | 
 | 1280 |     for(size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 1281 |         mpClientInterface->closeInput(mInputs.keyAt(input_index)); | 
 | 1282 |     } | 
 | 1283 |     mInputs.clear(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1284 |     nextAudioPortGeneration(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1285 | } | 
 | 1286 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1287 | void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1288 |                                             int indexMin, | 
 | 1289 |                                             int indexMax) | 
 | 1290 | { | 
 | 1291 |     ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax); | 
 | 1292 |     if (indexMin < 0 || indexMin >= indexMax) { | 
 | 1293 |         ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax); | 
 | 1294 |         return; | 
 | 1295 |     } | 
 | 1296 |     mStreams[stream].mIndexMin = indexMin; | 
 | 1297 |     mStreams[stream].mIndexMax = indexMax; | 
 | 1298 | } | 
 | 1299 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1300 | status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1301 |                                                       int index, | 
 | 1302 |                                                       audio_devices_t device) | 
 | 1303 | { | 
 | 1304 |  | 
 | 1305 |     if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) { | 
 | 1306 |         return BAD_VALUE; | 
 | 1307 |     } | 
 | 1308 |     if (!audio_is_output_device(device)) { | 
 | 1309 |         return BAD_VALUE; | 
 | 1310 |     } | 
 | 1311 |  | 
 | 1312 |     // Force max volume if stream cannot be muted | 
 | 1313 |     if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax; | 
 | 1314 |  | 
 | 1315 |     ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d", | 
 | 1316 |           stream, device, index); | 
 | 1317 |  | 
 | 1318 |     // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and | 
 | 1319 |     // clear all device specific values | 
 | 1320 |     if (device == AUDIO_DEVICE_OUT_DEFAULT) { | 
 | 1321 |         mStreams[stream].mIndexCur.clear(); | 
 | 1322 |     } | 
 | 1323 |     mStreams[stream].mIndexCur.add(device, index); | 
 | 1324 |  | 
 | 1325 |     // compute and apply stream volume on all outputs according to connected device | 
 | 1326 |     status_t status = NO_ERROR; | 
 | 1327 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1328 |         audio_devices_t curDevice = | 
 | 1329 |                 getDeviceForVolume(mOutputs.valueAt(i)->device()); | 
 | 1330 |         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)) { | 
 | 1331 |             status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice); | 
 | 1332 |             if (volStatus != NO_ERROR) { | 
 | 1333 |                 status = volStatus; | 
 | 1334 |             } | 
 | 1335 |         } | 
 | 1336 |     } | 
 | 1337 |     return status; | 
 | 1338 | } | 
 | 1339 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1340 | status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1341 |                                                       int *index, | 
 | 1342 |                                                       audio_devices_t device) | 
 | 1343 | { | 
 | 1344 |     if (index == NULL) { | 
 | 1345 |         return BAD_VALUE; | 
 | 1346 |     } | 
 | 1347 |     if (!audio_is_output_device(device)) { | 
 | 1348 |         return BAD_VALUE; | 
 | 1349 |     } | 
 | 1350 |     // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to | 
 | 1351 |     // the strategy the stream belongs to. | 
 | 1352 |     if (device == AUDIO_DEVICE_OUT_DEFAULT) { | 
 | 1353 |         device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/); | 
 | 1354 |     } | 
 | 1355 |     device = getDeviceForVolume(device); | 
 | 1356 |  | 
 | 1357 |     *index =  mStreams[stream].getVolumeIndex(device); | 
 | 1358 |     ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index); | 
 | 1359 |     return NO_ERROR; | 
 | 1360 | } | 
 | 1361 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1362 | audio_io_handle_t AudioPolicyManager::selectOutputForEffects( | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1363 |                                             const SortedVector<audio_io_handle_t>& outputs) | 
 | 1364 | { | 
 | 1365 |     // select one output among several suitable for global effects. | 
 | 1366 |     // The priority is as follows: | 
 | 1367 |     // 1: An offloaded output. If the effect ends up not being offloadable, | 
 | 1368 |     //    AudioFlinger will invalidate the track and the offloaded output | 
 | 1369 |     //    will be closed causing the effect to be moved to a PCM output. | 
 | 1370 |     // 2: A deep buffer output | 
 | 1371 |     // 3: the first output in the list | 
 | 1372 |  | 
 | 1373 |     if (outputs.size() == 0) { | 
 | 1374 |         return 0; | 
 | 1375 |     } | 
 | 1376 |  | 
 | 1377 |     audio_io_handle_t outputOffloaded = 0; | 
 | 1378 |     audio_io_handle_t outputDeepBuffer = 0; | 
 | 1379 |  | 
 | 1380 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1381 |         sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1382 |         ALOGV("selectOutputForEffects outputs[%zu] flags %x", i, desc->mFlags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1383 |         if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
 | 1384 |             outputOffloaded = outputs[i]; | 
 | 1385 |         } | 
 | 1386 |         if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) { | 
 | 1387 |             outputDeepBuffer = outputs[i]; | 
 | 1388 |         } | 
 | 1389 |     } | 
 | 1390 |  | 
 | 1391 |     ALOGV("selectOutputForEffects outputOffloaded %d outputDeepBuffer %d", | 
 | 1392 |           outputOffloaded, outputDeepBuffer); | 
 | 1393 |     if (outputOffloaded != 0) { | 
 | 1394 |         return outputOffloaded; | 
 | 1395 |     } | 
 | 1396 |     if (outputDeepBuffer != 0) { | 
 | 1397 |         return outputDeepBuffer; | 
 | 1398 |     } | 
 | 1399 |  | 
 | 1400 |     return outputs[0]; | 
 | 1401 | } | 
 | 1402 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1403 | audio_io_handle_t AudioPolicyManager::getOutputForEffect(const effect_descriptor_t *desc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1404 | { | 
 | 1405 |     // apply simple rule where global effects are attached to the same output as MUSIC streams | 
 | 1406 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1407 |     routing_strategy strategy = getStrategy(AUDIO_STREAM_MUSIC); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1408 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 1409 |     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(device, mOutputs); | 
 | 1410 |  | 
 | 1411 |     audio_io_handle_t output = selectOutputForEffects(dstOutputs); | 
 | 1412 |     ALOGV("getOutputForEffect() got output %d for fx %s flags %x", | 
 | 1413 |           output, (desc == NULL) ? "unspecified" : desc->name,  (desc == NULL) ? 0 : desc->flags); | 
 | 1414 |  | 
 | 1415 |     return output; | 
 | 1416 | } | 
 | 1417 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1418 | status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1419 |                                 audio_io_handle_t io, | 
 | 1420 |                                 uint32_t strategy, | 
 | 1421 |                                 int session, | 
 | 1422 |                                 int id) | 
 | 1423 | { | 
 | 1424 |     ssize_t index = mOutputs.indexOfKey(io); | 
 | 1425 |     if (index < 0) { | 
 | 1426 |         index = mInputs.indexOfKey(io); | 
 | 1427 |         if (index < 0) { | 
 | 1428 |             ALOGW("registerEffect() unknown io %d", io); | 
 | 1429 |             return INVALID_OPERATION; | 
 | 1430 |         } | 
 | 1431 |     } | 
 | 1432 |  | 
 | 1433 |     if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) { | 
 | 1434 |         ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB", | 
 | 1435 |                 desc->name, desc->memoryUsage); | 
 | 1436 |         return INVALID_OPERATION; | 
 | 1437 |     } | 
 | 1438 |     mTotalEffectsMemory += desc->memoryUsage; | 
 | 1439 |     ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d", | 
 | 1440 |             desc->name, io, strategy, session, id); | 
 | 1441 |     ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory); | 
 | 1442 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1443 |     sp<EffectDescriptor> effectDesc = new EffectDescriptor(); | 
 | 1444 |     memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t)); | 
 | 1445 |     effectDesc->mIo = io; | 
 | 1446 |     effectDesc->mStrategy = (routing_strategy)strategy; | 
 | 1447 |     effectDesc->mSession = session; | 
 | 1448 |     effectDesc->mEnabled = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1449 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1450 |     mEffects.add(id, effectDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1451 |  | 
 | 1452 |     return NO_ERROR; | 
 | 1453 | } | 
 | 1454 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1455 | status_t AudioPolicyManager::unregisterEffect(int id) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1456 | { | 
 | 1457 |     ssize_t index = mEffects.indexOfKey(id); | 
 | 1458 |     if (index < 0) { | 
 | 1459 |         ALOGW("unregisterEffect() unknown effect ID %d", id); | 
 | 1460 |         return INVALID_OPERATION; | 
 | 1461 |     } | 
 | 1462 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1463 |     sp<EffectDescriptor> effectDesc = mEffects.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1464 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1465 |     setEffectEnabled(effectDesc, false); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1466 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1467 |     if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1468 |         ALOGW("unregisterEffect() memory %d too big for total %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1469 |                 effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); | 
 | 1470 |         effectDesc->mDesc.memoryUsage = mTotalEffectsMemory; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1471 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1472 |     mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1473 |     ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1474 |             effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1475 |  | 
 | 1476 |     mEffects.removeItem(id); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1477 |  | 
 | 1478 |     return NO_ERROR; | 
 | 1479 | } | 
 | 1480 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1481 | status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1482 | { | 
 | 1483 |     ssize_t index = mEffects.indexOfKey(id); | 
 | 1484 |     if (index < 0) { | 
 | 1485 |         ALOGW("unregisterEffect() unknown effect ID %d", id); | 
 | 1486 |         return INVALID_OPERATION; | 
 | 1487 |     } | 
 | 1488 |  | 
 | 1489 |     return setEffectEnabled(mEffects.valueAt(index), enabled); | 
 | 1490 | } | 
 | 1491 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1492 | status_t AudioPolicyManager::setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1493 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1494 |     if (enabled == effectDesc->mEnabled) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1495 |         ALOGV("setEffectEnabled(%s) effect already %s", | 
 | 1496 |              enabled?"true":"false", enabled?"enabled":"disabled"); | 
 | 1497 |         return INVALID_OPERATION; | 
 | 1498 |     } | 
 | 1499 |  | 
 | 1500 |     if (enabled) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1501 |         if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1502 |             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] | 1503 |                  effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1504 |             return INVALID_OPERATION; | 
 | 1505 |         } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1506 |         mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1507 |         ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad); | 
 | 1508 |     } else { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1509 |         if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1510 |             ALOGW("setEffectEnabled(false) CPU load %d too high for total %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1511 |                     effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad); | 
 | 1512 |             effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1513 |         } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1514 |         mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1515 |         ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad); | 
 | 1516 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1517 |     effectDesc->mEnabled = enabled; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1518 |     return NO_ERROR; | 
 | 1519 | } | 
 | 1520 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1521 | bool AudioPolicyManager::isNonOffloadableEffectEnabled() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1522 | { | 
 | 1523 |     for (size_t i = 0; i < mEffects.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1524 |         sp<EffectDescriptor> effectDesc = mEffects.valueAt(i); | 
 | 1525 |         if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) && | 
 | 1526 |                 ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1527 |             ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1528 |                   effectDesc->mDesc.name, effectDesc->mSession); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1529 |             return true; | 
 | 1530 |         } | 
 | 1531 |     } | 
 | 1532 |     return false; | 
 | 1533 | } | 
 | 1534 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1535 | bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1536 | { | 
 | 1537 |     nsecs_t sysTime = systemTime(); | 
 | 1538 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1539 |         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1540 |         if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1541 |             return true; | 
 | 1542 |         } | 
 | 1543 |     } | 
 | 1544 |     return false; | 
 | 1545 | } | 
 | 1546 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1547 | bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1548 |                                                     uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1549 | { | 
 | 1550 |     nsecs_t sysTime = systemTime(); | 
 | 1551 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1552 |         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1553 |         if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1554 |                 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1555 |             return true; | 
 | 1556 |         } | 
 | 1557 |     } | 
 | 1558 |     return false; | 
 | 1559 | } | 
 | 1560 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1561 | bool AudioPolicyManager::isSourceActive(audio_source_t source) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1562 | { | 
 | 1563 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1564 |         const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1565 |         if ((inputDescriptor->mInputSource == (int)source || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1566 |                 (source == AUDIO_SOURCE_VOICE_RECOGNITION && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1567 |                  inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD)) | 
 | 1568 |              && (inputDescriptor->mRefCount > 0)) { | 
 | 1569 |             return true; | 
 | 1570 |         } | 
 | 1571 |     } | 
 | 1572 |     return false; | 
 | 1573 | } | 
 | 1574 |  | 
 | 1575 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1576 | status_t AudioPolicyManager::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1577 | { | 
 | 1578 |     const size_t SIZE = 256; | 
 | 1579 |     char buffer[SIZE]; | 
 | 1580 |     String8 result; | 
 | 1581 |  | 
 | 1582 |     snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this); | 
 | 1583 |     result.append(buffer); | 
 | 1584 |  | 
 | 1585 |     snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput); | 
 | 1586 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1587 |     snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState); | 
 | 1588 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1589 |     snprintf(buffer, SIZE, " Force use for communications %d\n", | 
 | 1590 |              mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1591 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1592 |     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] | 1593 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1594 |     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] | 1595 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1596 |     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] | 1597 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1598 |     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] | 1599 |     result.append(buffer); | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 1600 |     snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n", | 
 | 1601 |             mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]); | 
 | 1602 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1603 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1604 |     snprintf(buffer, SIZE, " Available output devices:\n"); | 
 | 1605 |     result.append(buffer); | 
 | 1606 |     write(fd, result.string(), result.size()); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1607 |     for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1608 |         mAvailableOutputDevices[i]->dump(fd, 2, i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1609 |     } | 
 | 1610 |     snprintf(buffer, SIZE, "\n Available input devices:\n"); | 
 | 1611 |     write(fd, buffer, strlen(buffer)); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1612 |     for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1613 |         mAvailableInputDevices[i]->dump(fd, 2, i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1614 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1615 |  | 
 | 1616 |     snprintf(buffer, SIZE, "\nHW Modules dump:\n"); | 
 | 1617 |     write(fd, buffer, strlen(buffer)); | 
 | 1618 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1619 |         snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1620 |         write(fd, buffer, strlen(buffer)); | 
 | 1621 |         mHwModules[i]->dump(fd); | 
 | 1622 |     } | 
 | 1623 |  | 
 | 1624 |     snprintf(buffer, SIZE, "\nOutputs dump:\n"); | 
 | 1625 |     write(fd, buffer, strlen(buffer)); | 
 | 1626 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1627 |         snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i)); | 
 | 1628 |         write(fd, buffer, strlen(buffer)); | 
 | 1629 |         mOutputs.valueAt(i)->dump(fd); | 
 | 1630 |     } | 
 | 1631 |  | 
 | 1632 |     snprintf(buffer, SIZE, "\nInputs dump:\n"); | 
 | 1633 |     write(fd, buffer, strlen(buffer)); | 
 | 1634 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 1635 |         snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i)); | 
 | 1636 |         write(fd, buffer, strlen(buffer)); | 
 | 1637 |         mInputs.valueAt(i)->dump(fd); | 
 | 1638 |     } | 
 | 1639 |  | 
 | 1640 |     snprintf(buffer, SIZE, "\nStreams dump:\n"); | 
 | 1641 |     write(fd, buffer, strlen(buffer)); | 
 | 1642 |     snprintf(buffer, SIZE, | 
 | 1643 |              " Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n"); | 
 | 1644 |     write(fd, buffer, strlen(buffer)); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 1645 |     for (size_t i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1646 |         snprintf(buffer, SIZE, " %02zu      ", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1647 |         write(fd, buffer, strlen(buffer)); | 
 | 1648 |         mStreams[i].dump(fd); | 
 | 1649 |     } | 
 | 1650 |  | 
 | 1651 |     snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n", | 
 | 1652 |             (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory); | 
 | 1653 |     write(fd, buffer, strlen(buffer)); | 
 | 1654 |  | 
 | 1655 |     snprintf(buffer, SIZE, "Registered effects:\n"); | 
 | 1656 |     write(fd, buffer, strlen(buffer)); | 
 | 1657 |     for (size_t i = 0; i < mEffects.size(); i++) { | 
 | 1658 |         snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i)); | 
 | 1659 |         write(fd, buffer, strlen(buffer)); | 
 | 1660 |         mEffects.valueAt(i)->dump(fd); | 
 | 1661 |     } | 
 | 1662 |  | 
 | 1663 |  | 
 | 1664 |     return NO_ERROR; | 
 | 1665 | } | 
 | 1666 |  | 
 | 1667 | // This function checks for the parameters which can be offloaded. | 
 | 1668 | // This can be enhanced depending on the capability of the DSP and policy | 
 | 1669 | // of the system. | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1670 | bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadInfo) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1671 | { | 
 | 1672 |     ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d," | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1673 |      " BitRate=%u, duration=%" PRId64 " us, has_video=%d", | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1674 |      offloadInfo.sample_rate, offloadInfo.channel_mask, | 
 | 1675 |      offloadInfo.format, | 
 | 1676 |      offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us, | 
 | 1677 |      offloadInfo.has_video); | 
 | 1678 |  | 
 | 1679 |     // Check if offload has been disabled | 
 | 1680 |     char propValue[PROPERTY_VALUE_MAX]; | 
 | 1681 |     if (property_get("audio.offload.disable", propValue, "0")) { | 
 | 1682 |         if (atoi(propValue) != 0) { | 
 | 1683 |             ALOGV("offload disabled by audio.offload.disable=%s", propValue ); | 
 | 1684 |             return false; | 
 | 1685 |         } | 
 | 1686 |     } | 
 | 1687 |  | 
 | 1688 |     // Check if stream type is music, then only allow offload as of now. | 
 | 1689 |     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC) | 
 | 1690 |     { | 
 | 1691 |         ALOGV("isOffloadSupported: stream_type != MUSIC, returning false"); | 
 | 1692 |         return false; | 
 | 1693 |     } | 
 | 1694 |  | 
 | 1695 |     //TODO: enable audio offloading with video when ready | 
 | 1696 |     if (offloadInfo.has_video) | 
 | 1697 |     { | 
 | 1698 |         ALOGV("isOffloadSupported: has_video == true, returning false"); | 
 | 1699 |         return false; | 
 | 1700 |     } | 
 | 1701 |  | 
 | 1702 |     //If duration is less than minimum value defined in property, return false | 
 | 1703 |     if (property_get("audio.offload.min.duration.secs", propValue, NULL)) { | 
 | 1704 |         if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) { | 
 | 1705 |             ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue); | 
 | 1706 |             return false; | 
 | 1707 |         } | 
 | 1708 |     } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) { | 
 | 1709 |         ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS); | 
 | 1710 |         return false; | 
 | 1711 |     } | 
 | 1712 |  | 
 | 1713 |     // Do not allow offloading if one non offloadable effect is enabled. This prevents from | 
 | 1714 |     // creating an offloaded track and tearing it down immediately after start when audioflinger | 
 | 1715 |     // detects there is an active non offloadable effect. | 
 | 1716 |     // FIXME: We should check the audio session here but we do not have it in this context. | 
 | 1717 |     // This may prevent offloading in rare situations where effects are left active by apps | 
 | 1718 |     // in the background. | 
 | 1719 |     if (isNonOffloadableEffectEnabled()) { | 
 | 1720 |         return false; | 
 | 1721 |     } | 
 | 1722 |  | 
 | 1723 |     // See if there is a profile to support this. | 
 | 1724 |     // AUDIO_DEVICE_NONE | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1725 |     sp<IOProfile> profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1726 |                                             offloadInfo.sample_rate, | 
 | 1727 |                                             offloadInfo.format, | 
 | 1728 |                                             offloadInfo.channel_mask, | 
 | 1729 |                                             AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1730 |     ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT "); | 
 | 1731 |     return (profile != 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1732 | } | 
 | 1733 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1734 | status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role, | 
 | 1735 |                                             audio_port_type_t type, | 
 | 1736 |                                             unsigned int *num_ports, | 
 | 1737 |                                             struct audio_port *ports, | 
 | 1738 |                                             unsigned int *generation) | 
 | 1739 | { | 
 | 1740 |     if (num_ports == NULL || (*num_ports != 0 && ports == NULL) || | 
 | 1741 |             generation == NULL) { | 
 | 1742 |         return BAD_VALUE; | 
 | 1743 |     } | 
 | 1744 |     ALOGV("listAudioPorts() role %d type %d num_ports %d ports %p", role, type, *num_ports, ports); | 
 | 1745 |     if (ports == NULL) { | 
 | 1746 |         *num_ports = 0; | 
 | 1747 |     } | 
 | 1748 |  | 
 | 1749 |     size_t portsWritten = 0; | 
 | 1750 |     size_t portsMax = *num_ports; | 
 | 1751 |     *num_ports = 0; | 
 | 1752 |     if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 1753 |         if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) { | 
 | 1754 |             for (size_t i = 0; | 
 | 1755 |                     i  < mAvailableOutputDevices.size() && portsWritten < portsMax; i++) { | 
 | 1756 |                 mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1757 |             } | 
 | 1758 |             *num_ports += mAvailableOutputDevices.size(); | 
 | 1759 |         } | 
 | 1760 |         if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) { | 
 | 1761 |             for (size_t i = 0; | 
 | 1762 |                     i  < mAvailableInputDevices.size() && portsWritten < portsMax; i++) { | 
 | 1763 |                 mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1764 |             } | 
 | 1765 |             *num_ports += mAvailableInputDevices.size(); | 
 | 1766 |         } | 
 | 1767 |     } | 
 | 1768 |     if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_MIX) { | 
 | 1769 |         if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) { | 
 | 1770 |             for (size_t i = 0; i < mInputs.size() && portsWritten < portsMax; i++) { | 
 | 1771 |                 mInputs[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1772 |             } | 
 | 1773 |             *num_ports += mInputs.size(); | 
 | 1774 |         } | 
 | 1775 |         if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1776 |             size_t numOutputs = 0; | 
 | 1777 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1778 |                 if (!mOutputs[i]->isDuplicated()) { | 
 | 1779 |                     numOutputs++; | 
 | 1780 |                     if (portsWritten < portsMax) { | 
 | 1781 |                         mOutputs[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1782 |                     } | 
 | 1783 |                 } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1784 |             } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1785 |             *num_ports += numOutputs; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1786 |         } | 
 | 1787 |     } | 
 | 1788 |     *generation = curAudioPortGeneration(); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 1789 |     ALOGV("listAudioPorts() got %zu ports needed %d", portsWritten, *num_ports); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1790 |     return NO_ERROR; | 
 | 1791 | } | 
 | 1792 |  | 
 | 1793 | status_t AudioPolicyManager::getAudioPort(struct audio_port *port __unused) | 
 | 1794 | { | 
 | 1795 |     return NO_ERROR; | 
 | 1796 | } | 
 | 1797 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1798 | sp<AudioPolicyManager::AudioOutputDescriptor> AudioPolicyManager::getOutputFromId( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1799 |                                                                     audio_port_handle_t id) const | 
 | 1800 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1801 |     sp<AudioOutputDescriptor> outputDesc = NULL; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1802 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1803 |         outputDesc = mOutputs.valueAt(i); | 
 | 1804 |         if (outputDesc->mId == id) { | 
 | 1805 |             break; | 
 | 1806 |         } | 
 | 1807 |     } | 
 | 1808 |     return outputDesc; | 
 | 1809 | } | 
 | 1810 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1811 | sp<AudioPolicyManager::AudioInputDescriptor> AudioPolicyManager::getInputFromId( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1812 |                                                                     audio_port_handle_t id) const | 
 | 1813 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1814 |     sp<AudioInputDescriptor> inputDesc = NULL; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1815 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 1816 |         inputDesc = mInputs.valueAt(i); | 
 | 1817 |         if (inputDesc->mId == id) { | 
 | 1818 |             break; | 
 | 1819 |         } | 
 | 1820 |     } | 
 | 1821 |     return inputDesc; | 
 | 1822 | } | 
 | 1823 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1824 | sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleForDevice( | 
 | 1825 |                                                                     audio_devices_t device) const | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1826 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1827 |     sp <HwModule> module; | 
 | 1828 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1829 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 1830 |         if (mHwModules[i]->mHandle == 0) { | 
 | 1831 |             continue; | 
 | 1832 |         } | 
 | 1833 |         if (audio_is_output_device(device)) { | 
 | 1834 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 1835 |             { | 
 | 1836 |                 if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) { | 
 | 1837 |                     return mHwModules[i]; | 
 | 1838 |                 } | 
 | 1839 |             } | 
 | 1840 |         } else { | 
 | 1841 |             for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) { | 
 | 1842 |                 if (mHwModules[i]->mInputProfiles[j]->mSupportedDevices.types() & | 
 | 1843 |                         device & ~AUDIO_DEVICE_BIT_IN) { | 
 | 1844 |                     return mHwModules[i]; | 
 | 1845 |                 } | 
 | 1846 |             } | 
 | 1847 |         } | 
 | 1848 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1849 |     return module; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1850 | } | 
 | 1851 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1852 | sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleFromName(const char *name) const | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1853 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1854 |     sp <HwModule> module; | 
 | 1855 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1856 |     for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 1857 |     { | 
 | 1858 |         if (strcmp(mHwModules[i]->mName, name) == 0) { | 
 | 1859 |             return mHwModules[i]; | 
 | 1860 |         } | 
 | 1861 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1862 |     return module; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1863 | } | 
 | 1864 |  | 
 | 1865 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1866 | status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, | 
 | 1867 |                                                audio_patch_handle_t *handle, | 
 | 1868 |                                                uid_t uid) | 
 | 1869 | { | 
 | 1870 |     ALOGV("createAudioPatch()"); | 
 | 1871 |  | 
 | 1872 |     if (handle == NULL || patch == NULL) { | 
 | 1873 |         return BAD_VALUE; | 
 | 1874 |     } | 
 | 1875 |     ALOGV("createAudioPatch() num sources %d num sinks %d", patch->num_sources, patch->num_sinks); | 
 | 1876 |  | 
 | 1877 |     if (patch->num_sources > 1 || patch->num_sinks > 1) { | 
 | 1878 |         return INVALID_OPERATION; | 
 | 1879 |     } | 
 | 1880 |     if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE || | 
 | 1881 |             patch->sinks[0].role != AUDIO_PORT_ROLE_SINK) { | 
 | 1882 |         return INVALID_OPERATION; | 
 | 1883 |     } | 
 | 1884 |  | 
 | 1885 |     sp<AudioPatch> patchDesc; | 
 | 1886 |     ssize_t index = mAudioPatches.indexOfKey(*handle); | 
 | 1887 |  | 
 | 1888 |     ALOGV("createAudioPatch sink id %d role %d type %d", patch->sinks[0].id, patch->sinks[0].role, | 
 | 1889 |                                                          patch->sinks[0].type); | 
 | 1890 |     ALOGV("createAudioPatch source id %d role %d type %d", patch->sources[0].id, | 
 | 1891 |                                                            patch->sources[0].role, | 
 | 1892 |                                                            patch->sources[0].type); | 
 | 1893 |  | 
 | 1894 |     if (index >= 0) { | 
 | 1895 |         patchDesc = mAudioPatches.valueAt(index); | 
 | 1896 |         ALOGV("createAudioPatch() mUidCached %d patchDesc->mUid %d uid %d", | 
 | 1897 |                                                                   mUidCached, patchDesc->mUid, uid); | 
 | 1898 |         if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) { | 
 | 1899 |             return INVALID_OPERATION; | 
 | 1900 |         } | 
 | 1901 |     } else { | 
 | 1902 |         *handle = 0; | 
 | 1903 |     } | 
 | 1904 |  | 
 | 1905 |     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { | 
 | 1906 |         // TODO add support for mix to mix connection | 
 | 1907 |         if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { | 
 | 1908 |             ALOGV("createAudioPatch() source mix sink not device"); | 
 | 1909 |             return BAD_VALUE; | 
 | 1910 |         } | 
 | 1911 |         // output mix to output device connection | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1912 |         sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1913 |         if (outputDesc == NULL) { | 
 | 1914 |             ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id); | 
 | 1915 |             return BAD_VALUE; | 
 | 1916 |         } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1917 |         ALOG_ASSERT(!outputDesc->isDuplicated(),"duplicated output %d in source in ports", | 
 | 1918 |                                                 outputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1919 |         if (patchDesc != 0) { | 
 | 1920 |             if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) { | 
 | 1921 |                 ALOGV("createAudioPatch() source id differs for patch current id %d new id %d", | 
 | 1922 |                                           patchDesc->mPatch.sources[0].id, patch->sources[0].id); | 
 | 1923 |                 return BAD_VALUE; | 
 | 1924 |             } | 
 | 1925 |         } | 
 | 1926 |         sp<DeviceDescriptor> devDesc = | 
 | 1927 |                 mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); | 
 | 1928 |         if (devDesc == 0) { | 
 | 1929 |             ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[0].id); | 
 | 1930 |             return BAD_VALUE; | 
 | 1931 |         } | 
 | 1932 |  | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1933 |         if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1934 |                                                        patch->sources[0].sample_rate, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 1935 |                                                      NULL,  // updatedSamplingRate | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1936 |                                                      patch->sources[0].format, | 
 | 1937 |                                                      patch->sources[0].channel_mask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1938 |                                                      AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1939 |             ALOGV("createAudioPatch() profile not supported"); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1940 |             return INVALID_OPERATION; | 
 | 1941 |         } | 
 | 1942 |         // TODO: reconfigure output format and channels here | 
 | 1943 |         ALOGV("createAudioPatch() setting device %08x on output %d", | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1944 |                                               devDesc->mDeviceType, outputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1945 |         setOutputDevice(outputDesc->mIoHandle, | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1946 |                         devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1947 |                        true, | 
 | 1948 |                        0, | 
 | 1949 |                        handle); | 
 | 1950 |         index = mAudioPatches.indexOfKey(*handle); | 
 | 1951 |         if (index >= 0) { | 
 | 1952 |             if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { | 
 | 1953 |                 ALOGW("createAudioPatch() setOutputDevice() did not reuse the patch provided"); | 
 | 1954 |             } | 
 | 1955 |             patchDesc = mAudioPatches.valueAt(index); | 
 | 1956 |             patchDesc->mUid = uid; | 
 | 1957 |             ALOGV("createAudioPatch() success"); | 
 | 1958 |         } else { | 
 | 1959 |             ALOGW("createAudioPatch() setOutputDevice() failed to create a patch"); | 
 | 1960 |             return INVALID_OPERATION; | 
 | 1961 |         } | 
 | 1962 |     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 1963 |         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { | 
 | 1964 |             // input device to input mix connection | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1965 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1966 |             if (inputDesc == NULL) { | 
 | 1967 |                 return BAD_VALUE; | 
 | 1968 |             } | 
 | 1969 |             if (patchDesc != 0) { | 
 | 1970 |                 if (patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { | 
 | 1971 |                     return BAD_VALUE; | 
 | 1972 |                 } | 
 | 1973 |             } | 
 | 1974 |             sp<DeviceDescriptor> devDesc = | 
 | 1975 |                     mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); | 
 | 1976 |             if (devDesc == 0) { | 
 | 1977 |                 return BAD_VALUE; | 
 | 1978 |             } | 
 | 1979 |  | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1980 |             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 1981 |                                                          patch->sinks[0].sample_rate, | 
 | 1982 |                                                          NULL, /*updatedSampleRate*/ | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1983 |                                                          patch->sinks[0].format, | 
 | 1984 |                                                          patch->sinks[0].channel_mask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 1985 |                                                          // FIXME for the parameter type, | 
 | 1986 |                                                          // and the NONE | 
 | 1987 |                                                          (audio_output_flags_t) | 
 | 1988 |                                                             AUDIO_INPUT_FLAG_NONE)) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1989 |                 return INVALID_OPERATION; | 
 | 1990 |             } | 
 | 1991 |             // TODO: reconfigure output format and channels here | 
 | 1992 |             ALOGV("createAudioPatch() setting device %08x on output %d", | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1993 |                                                   devDesc->mDeviceType, inputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1994 |             setInputDevice(inputDesc->mIoHandle, | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1995 |                            devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1996 |                            true, | 
 | 1997 |                            handle); | 
 | 1998 |             index = mAudioPatches.indexOfKey(*handle); | 
 | 1999 |             if (index >= 0) { | 
 | 2000 |                 if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { | 
 | 2001 |                     ALOGW("createAudioPatch() setInputDevice() did not reuse the patch provided"); | 
 | 2002 |                 } | 
 | 2003 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 2004 |                 patchDesc->mUid = uid; | 
 | 2005 |                 ALOGV("createAudioPatch() success"); | 
 | 2006 |             } else { | 
 | 2007 |                 ALOGW("createAudioPatch() setInputDevice() failed to create a patch"); | 
 | 2008 |                 return INVALID_OPERATION; | 
 | 2009 |             } | 
 | 2010 |         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2011 |             // device to device connection | 
 | 2012 |             if (patchDesc != 0) { | 
 | 2013 |                 if (patchDesc->mPatch.sources[0].id != patch->sources[0].id && | 
 | 2014 |                     patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { | 
 | 2015 |                     return BAD_VALUE; | 
 | 2016 |                 } | 
 | 2017 |             } | 
 | 2018 |  | 
 | 2019 |             sp<DeviceDescriptor> srcDeviceDesc = | 
 | 2020 |                     mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); | 
 | 2021 |             sp<DeviceDescriptor> sinkDeviceDesc = | 
 | 2022 |                     mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); | 
 | 2023 |             if (srcDeviceDesc == 0 || sinkDeviceDesc == 0) { | 
 | 2024 |                 return BAD_VALUE; | 
 | 2025 |             } | 
 | 2026 |             //update source and sink with our own data as the data passed in the patch may | 
 | 2027 |             // be incomplete. | 
 | 2028 |             struct audio_patch newPatch = *patch; | 
 | 2029 |             srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]); | 
 | 2030 |             sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[0], &patch->sinks[0]); | 
 | 2031 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2032 |             if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2033 |                 SortedVector<audio_io_handle_t> outputs = | 
 | 2034 |                                         getOutputsForDevice(sinkDeviceDesc->mDeviceType, mOutputs); | 
 | 2035 |                 // if the sink device is reachable via an opened output stream, request to go via | 
 | 2036 |                 // this output stream by adding a second source to the patch description | 
 | 2037 |                 audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE); | 
 | 2038 |                 if (output != AUDIO_IO_HANDLE_NONE) { | 
 | 2039 |                     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
 | 2040 |                     if (outputDesc->isDuplicated()) { | 
 | 2041 |                         return INVALID_OPERATION; | 
 | 2042 |                     } | 
 | 2043 |                     outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]); | 
 | 2044 |                     newPatch.num_sources = 2; | 
 | 2045 |                 } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2046 |             } | 
 | 2047 |             // TODO: check from routing capabilities in config file and other conflicting patches | 
 | 2048 |  | 
 | 2049 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 2050 |             if (index >= 0) { | 
 | 2051 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 2052 |             } | 
 | 2053 |  | 
 | 2054 |             status_t status = mpClientInterface->createAudioPatch(&newPatch, | 
 | 2055 |                                                                   &afPatchHandle, | 
 | 2056 |                                                                   0); | 
 | 2057 |             ALOGV("createAudioPatch() patch panel returned %d patchHandle %d", | 
 | 2058 |                                                                   status, afPatchHandle); | 
 | 2059 |             if (status == NO_ERROR) { | 
 | 2060 |                 if (index < 0) { | 
 | 2061 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 2062 |                                                &newPatch, uid); | 
 | 2063 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 2064 |                 } else { | 
 | 2065 |                     patchDesc->mPatch = newPatch; | 
 | 2066 |                 } | 
 | 2067 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 2068 |                 *handle = patchDesc->mHandle; | 
 | 2069 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 2070 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2071 |             } else { | 
 | 2072 |                 ALOGW("createAudioPatch() patch panel could not connect device patch, error %d", | 
 | 2073 |                 status); | 
 | 2074 |                 return INVALID_OPERATION; | 
 | 2075 |             } | 
 | 2076 |         } else { | 
 | 2077 |             return BAD_VALUE; | 
 | 2078 |         } | 
 | 2079 |     } else { | 
 | 2080 |         return BAD_VALUE; | 
 | 2081 |     } | 
 | 2082 |     return NO_ERROR; | 
 | 2083 | } | 
 | 2084 |  | 
 | 2085 | status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle, | 
 | 2086 |                                                   uid_t uid) | 
 | 2087 | { | 
 | 2088 |     ALOGV("releaseAudioPatch() patch %d", handle); | 
 | 2089 |  | 
 | 2090 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2091 |  | 
 | 2092 |     if (index < 0) { | 
 | 2093 |         return BAD_VALUE; | 
 | 2094 |     } | 
 | 2095 |     sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 2096 |     ALOGV("releaseAudioPatch() mUidCached %d patchDesc->mUid %d uid %d", | 
 | 2097 |           mUidCached, patchDesc->mUid, uid); | 
 | 2098 |     if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) { | 
 | 2099 |         return INVALID_OPERATION; | 
 | 2100 |     } | 
 | 2101 |  | 
 | 2102 |     struct audio_patch *patch = &patchDesc->mPatch; | 
 | 2103 |     patchDesc->mUid = mUidCached; | 
 | 2104 |     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2105 |         sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2106 |         if (outputDesc == NULL) { | 
 | 2107 |             ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id); | 
 | 2108 |             return BAD_VALUE; | 
 | 2109 |         } | 
 | 2110 |  | 
 | 2111 |         setOutputDevice(outputDesc->mIoHandle, | 
 | 2112 |                         getNewOutputDevice(outputDesc->mIoHandle, true /*fromCache*/), | 
 | 2113 |                        true, | 
 | 2114 |                        0, | 
 | 2115 |                        NULL); | 
 | 2116 |     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2117 |         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2118 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2119 |             if (inputDesc == NULL) { | 
 | 2120 |                 ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id); | 
 | 2121 |                 return BAD_VALUE; | 
 | 2122 |             } | 
 | 2123 |             setInputDevice(inputDesc->mIoHandle, | 
 | 2124 |                            getNewInputDevice(inputDesc->mIoHandle), | 
 | 2125 |                            true, | 
 | 2126 |                            NULL); | 
 | 2127 |         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2128 |             audio_patch_handle_t afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 2129 |             status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
 | 2130 |             ALOGV("releaseAudioPatch() patch panel returned %d patchHandle %d", | 
 | 2131 |                                                               status, patchDesc->mAfPatchHandle); | 
 | 2132 |             removeAudioPatch(patchDesc->mHandle); | 
 | 2133 |             nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 2134 |             mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2135 |         } else { | 
 | 2136 |             return BAD_VALUE; | 
 | 2137 |         } | 
 | 2138 |     } else { | 
 | 2139 |         return BAD_VALUE; | 
 | 2140 |     } | 
 | 2141 |     return NO_ERROR; | 
 | 2142 | } | 
 | 2143 |  | 
 | 2144 | status_t AudioPolicyManager::listAudioPatches(unsigned int *num_patches, | 
 | 2145 |                                               struct audio_patch *patches, | 
 | 2146 |                                               unsigned int *generation) | 
 | 2147 | { | 
 | 2148 |     if (num_patches == NULL || (*num_patches != 0 && patches == NULL) || | 
 | 2149 |             generation == NULL) { | 
 | 2150 |         return BAD_VALUE; | 
 | 2151 |     } | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2152 |     ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2153 |           *num_patches, patches, mAudioPatches.size()); | 
 | 2154 |     if (patches == NULL) { | 
 | 2155 |         *num_patches = 0; | 
 | 2156 |     } | 
 | 2157 |  | 
 | 2158 |     size_t patchesWritten = 0; | 
 | 2159 |     size_t patchesMax = *num_patches; | 
 | 2160 |     for (size_t i = 0; | 
 | 2161 |             i  < mAudioPatches.size() && patchesWritten < patchesMax; i++) { | 
 | 2162 |         patches[patchesWritten] = mAudioPatches[i]->mPatch; | 
 | 2163 |         patches[patchesWritten++].id = mAudioPatches[i]->mHandle; | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2164 |         ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2165 |               i, mAudioPatches[i]->mPatch.num_sources, mAudioPatches[i]->mPatch.num_sinks); | 
 | 2166 |     } | 
 | 2167 |     *num_patches = mAudioPatches.size(); | 
 | 2168 |  | 
 | 2169 |     *generation = curAudioPortGeneration(); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2170 |     ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2171 |     return NO_ERROR; | 
 | 2172 | } | 
 | 2173 |  | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2174 | status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config) | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2175 | { | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2176 |     ALOGV("setAudioPortConfig()"); | 
 | 2177 |  | 
 | 2178 |     if (config == NULL) { | 
 | 2179 |         return BAD_VALUE; | 
 | 2180 |     } | 
 | 2181 |     ALOGV("setAudioPortConfig() on port handle %d", config->id); | 
 | 2182 |     // Only support gain configuration for now | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2183 |     if (config->config_mask != AUDIO_PORT_CONFIG_GAIN) { | 
 | 2184 |         return INVALID_OPERATION; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2185 |     } | 
 | 2186 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2187 |     sp<AudioPortConfig> audioPortConfig; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2188 |     if (config->type == AUDIO_PORT_TYPE_MIX) { | 
 | 2189 |         if (config->role == AUDIO_PORT_ROLE_SOURCE) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2190 |             sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2191 |             if (outputDesc == NULL) { | 
 | 2192 |                 return BAD_VALUE; | 
 | 2193 |             } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2194 |             ALOG_ASSERT(!outputDesc->isDuplicated(), | 
 | 2195 |                         "setAudioPortConfig() called on duplicated output %d", | 
 | 2196 |                         outputDesc->mIoHandle); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2197 |             audioPortConfig = outputDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2198 |         } else if (config->role == AUDIO_PORT_ROLE_SINK) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2199 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2200 |             if (inputDesc == NULL) { | 
 | 2201 |                 return BAD_VALUE; | 
 | 2202 |             } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2203 |             audioPortConfig = inputDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2204 |         } else { | 
 | 2205 |             return BAD_VALUE; | 
 | 2206 |         } | 
 | 2207 |     } else if (config->type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2208 |         sp<DeviceDescriptor> deviceDesc; | 
 | 2209 |         if (config->role == AUDIO_PORT_ROLE_SOURCE) { | 
 | 2210 |             deviceDesc = mAvailableInputDevices.getDeviceFromId(config->id); | 
 | 2211 |         } else if (config->role == AUDIO_PORT_ROLE_SINK) { | 
 | 2212 |             deviceDesc = mAvailableOutputDevices.getDeviceFromId(config->id); | 
 | 2213 |         } else { | 
 | 2214 |             return BAD_VALUE; | 
 | 2215 |         } | 
 | 2216 |         if (deviceDesc == NULL) { | 
 | 2217 |             return BAD_VALUE; | 
 | 2218 |         } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2219 |         audioPortConfig = deviceDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2220 |     } else { | 
 | 2221 |         return BAD_VALUE; | 
 | 2222 |     } | 
 | 2223 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2224 |     struct audio_port_config backupConfig; | 
 | 2225 |     status_t status = audioPortConfig->applyAudioPortConfig(config, &backupConfig); | 
 | 2226 |     if (status == NO_ERROR) { | 
 | 2227 |         struct audio_port_config newConfig; | 
 | 2228 |         audioPortConfig->toAudioPortConfig(&newConfig, config); | 
 | 2229 |         status = mpClientInterface->setAudioPortConfig(&newConfig, 0); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2230 |     } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2231 |     if (status != NO_ERROR) { | 
 | 2232 |         audioPortConfig->applyAudioPortConfig(&backupConfig); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2233 |     } | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2234 |  | 
 | 2235 |     return status; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2236 | } | 
 | 2237 |  | 
 | 2238 | void AudioPolicyManager::clearAudioPatches(uid_t uid) | 
 | 2239 | { | 
 | 2240 |     for (ssize_t i = 0; i < (ssize_t)mAudioPatches.size(); i++)  { | 
 | 2241 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(i); | 
 | 2242 |         if (patchDesc->mUid == uid) { | 
 | 2243 |             // releaseAudioPatch() removes the patch from mAudioPatches | 
 | 2244 |             if (releaseAudioPatch(mAudioPatches.keyAt(i), uid) == NO_ERROR) { | 
 | 2245 |                 i--; | 
 | 2246 |             } | 
 | 2247 |         } | 
 | 2248 |     } | 
 | 2249 | } | 
 | 2250 |  | 
 | 2251 | status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle, | 
 | 2252 |                                            const sp<AudioPatch>& patch) | 
 | 2253 | { | 
 | 2254 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2255 |  | 
 | 2256 |     if (index >= 0) { | 
 | 2257 |         ALOGW("addAudioPatch() patch %d already in", handle); | 
 | 2258 |         return ALREADY_EXISTS; | 
 | 2259 |     } | 
 | 2260 |     mAudioPatches.add(handle, patch); | 
 | 2261 |     ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d" | 
 | 2262 |             "sink handle %d", | 
 | 2263 |           handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks, | 
 | 2264 |           patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id); | 
 | 2265 |     return NO_ERROR; | 
 | 2266 | } | 
 | 2267 |  | 
 | 2268 | status_t AudioPolicyManager::removeAudioPatch(audio_patch_handle_t handle) | 
 | 2269 | { | 
 | 2270 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2271 |  | 
 | 2272 |     if (index < 0) { | 
 | 2273 |         ALOGW("removeAudioPatch() patch %d not in", handle); | 
 | 2274 |         return ALREADY_EXISTS; | 
 | 2275 |     } | 
 | 2276 |     ALOGV("removeAudioPatch() handle %d af handle %d", handle, | 
 | 2277 |                       mAudioPatches.valueAt(index)->mAfPatchHandle); | 
 | 2278 |     mAudioPatches.removeItemsAt(index); | 
 | 2279 |     return NO_ERROR; | 
 | 2280 | } | 
 | 2281 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2282 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2283 | // AudioPolicyManager | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2284 | // ---------------------------------------------------------------------------- | 
 | 2285 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2286 | uint32_t AudioPolicyManager::nextUniqueId() | 
 | 2287 | { | 
 | 2288 |     return android_atomic_inc(&mNextUniqueId); | 
 | 2289 | } | 
 | 2290 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2291 | uint32_t AudioPolicyManager::nextAudioPortGeneration() | 
 | 2292 | { | 
 | 2293 |     return android_atomic_inc(&mAudioPortGeneration); | 
 | 2294 | } | 
 | 2295 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2296 | AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2297 |     : | 
 | 2298 | #ifdef AUDIO_POLICY_TEST | 
 | 2299 |     Thread(false), | 
 | 2300 | #endif //AUDIO_POLICY_TEST | 
 | 2301 |     mPrimaryOutput((audio_io_handle_t)0), | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2302 |     mPhoneState(AUDIO_MODE_NORMAL), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2303 |     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), | 
 | 2304 |     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2305 |     mA2dpSuspended(false), | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2306 |     mSpeakerDrcEnabled(false), mNextUniqueId(1), | 
 | 2307 |     mAudioPortGeneration(1) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2308 | { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2309 |     mUidCached = getuid(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2310 |     mpClientInterface = clientInterface; | 
 | 2311 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2312 |     for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) { | 
 | 2313 |         mForceUse[i] = AUDIO_POLICY_FORCE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2314 |     } | 
 | 2315 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2316 |     mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2317 |     if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) { | 
 | 2318 |         if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { | 
 | 2319 |             ALOGE("could not load audio policy configuration file, setting defaults"); | 
 | 2320 |             defaultAudioPolicyConfig(); | 
 | 2321 |         } | 
 | 2322 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2323 |     // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2324 |  | 
 | 2325 |     // must be done after reading the policy | 
 | 2326 |     initializeVolumeCurves(); | 
 | 2327 |  | 
 | 2328 |     // open all output streams needed to access attached devices | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2329 |     audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types(); | 
 | 2330 |     audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2331 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 2332 |         mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName); | 
 | 2333 |         if (mHwModules[i]->mHandle == 0) { | 
 | 2334 |             ALOGW("could not open HW module %s", mHwModules[i]->mName); | 
 | 2335 |             continue; | 
 | 2336 |         } | 
 | 2337 |         // open all output streams needed to access attached devices | 
 | 2338 |         // except for direct output streams that are only opened when they are actually | 
 | 2339 |         // required by an app. | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2340 |         // This also validates mAvailableOutputDevices list | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2341 |         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2342 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2343 |             const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2344 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2345 |             if (outProfile->mSupportedDevices.isEmpty()) { | 
 | 2346 |                 ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName); | 
 | 2347 |                 continue; | 
 | 2348 |             } | 
 | 2349 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2350 |             audio_devices_t profileType = outProfile->mSupportedDevices.types(); | 
 | 2351 |             if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) { | 
 | 2352 |                 profileType = mDefaultOutputDevice->mDeviceType; | 
 | 2353 |             } else { | 
 | 2354 |                 profileType = outProfile->mSupportedDevices[0]->mDeviceType; | 
 | 2355 |             } | 
 | 2356 |             if ((profileType & outputDeviceTypes) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2357 |                     ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2358 |                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2359 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2360 |                 outputDesc->mDevice = profileType; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2361 |                 audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 2362 |                 config.sample_rate = outputDesc->mSamplingRate; | 
 | 2363 |                 config.channel_mask = outputDesc->mChannelMask; | 
 | 2364 |                 config.format = outputDesc->mFormat; | 
 | 2365 |                 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; | 
 | 2366 |                 status_t status = mpClientInterface->openOutput(outProfile->mModule->mHandle, | 
 | 2367 |                                                                 &output, | 
 | 2368 |                                                                 &config, | 
 | 2369 |                                                                 &outputDesc->mDevice, | 
 | 2370 |                                                                 String8(""), | 
 | 2371 |                                                                 &outputDesc->mLatency, | 
 | 2372 |                                                                 outputDesc->mFlags); | 
 | 2373 |  | 
 | 2374 |                 if (status != NO_ERROR) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2375 |                     ALOGW("Cannot open output stream for device %08x on hw module %s", | 
 | 2376 |                           outputDesc->mDevice, | 
 | 2377 |                           mHwModules[i]->mName); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2378 |                 } else { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2379 |                     outputDesc->mSamplingRate = config.sample_rate; | 
 | 2380 |                     outputDesc->mChannelMask = config.channel_mask; | 
 | 2381 |                     outputDesc->mFormat = config.format; | 
 | 2382 |  | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2383 |                     for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2384 |                         audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2385 |                         ssize_t index = | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2386 |                                 mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2387 |                         // give a valid ID to an attached device once confirmed it is reachable | 
 | 2388 |                         if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) { | 
 | 2389 |                             mAvailableOutputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2390 |                             mAvailableOutputDevices[index]->mModule = mHwModules[i]; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2391 |                         } | 
 | 2392 |                     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2393 |                     if (mPrimaryOutput == 0 && | 
 | 2394 |                             outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { | 
 | 2395 |                         mPrimaryOutput = output; | 
 | 2396 |                     } | 
 | 2397 |                     addOutput(output, outputDesc); | 
 | 2398 |                     setOutputDevice(output, | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2399 |                                     outputDesc->mDevice, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2400 |                                     true); | 
 | 2401 |                 } | 
 | 2402 |             } | 
 | 2403 |         } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2404 |         // open input streams needed to access attached devices to validate | 
 | 2405 |         // mAvailableInputDevices list | 
 | 2406 |         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) | 
 | 2407 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2408 |             const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2409 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2410 |             if (inProfile->mSupportedDevices.isEmpty()) { | 
 | 2411 |                 ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName); | 
 | 2412 |                 continue; | 
 | 2413 |             } | 
 | 2414 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2415 |             audio_devices_t profileType = inProfile->mSupportedDevices[0]->mDeviceType; | 
 | 2416 |             if (profileType & inputDeviceTypes) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2417 |                 sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2418 |  | 
 | 2419 |                 inputDesc->mInputSource = AUDIO_SOURCE_MIC; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2420 |                 inputDesc->mDevice = profileType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2421 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2422 |                 audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 2423 |                 config.sample_rate = inputDesc->mSamplingRate; | 
 | 2424 |                 config.channel_mask = inputDesc->mChannelMask; | 
 | 2425 |                 config.format = inputDesc->mFormat; | 
 | 2426 |                 audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; | 
 | 2427 |                 status_t status = mpClientInterface->openInput(inProfile->mModule->mHandle, | 
 | 2428 |                                                                &input, | 
 | 2429 |                                                                &config, | 
 | 2430 |                                                                &inputDesc->mDevice, | 
 | 2431 |                                                                String8(""), | 
 | 2432 |                                                                AUDIO_SOURCE_MIC, | 
 | 2433 |                                                                AUDIO_INPUT_FLAG_NONE); | 
 | 2434 |  | 
 | 2435 |                 if (status == NO_ERROR) { | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2436 |                     for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2437 |                         audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2438 |                         ssize_t index = | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2439 |                                 mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2440 |                         // give a valid ID to an attached device once confirmed it is reachable | 
 | 2441 |                         if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) { | 
 | 2442 |                             mAvailableInputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2443 |                             mAvailableInputDevices[index]->mModule = mHwModules[i]; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2444 |                         } | 
 | 2445 |                     } | 
 | 2446 |                     mpClientInterface->closeInput(input); | 
 | 2447 |                 } else { | 
 | 2448 |                     ALOGW("Cannot open input stream for device %08x on hw module %s", | 
 | 2449 |                           inputDesc->mDevice, | 
 | 2450 |                           mHwModules[i]->mName); | 
 | 2451 |                 } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2452 |             } | 
 | 2453 |         } | 
 | 2454 |     } | 
 | 2455 |     // make sure all attached devices have been allocated a unique ID | 
 | 2456 |     for (size_t i = 0; i  < mAvailableOutputDevices.size();) { | 
 | 2457 |         if (mAvailableOutputDevices[i]->mId == 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2458 |             ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2459 |             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]); | 
 | 2460 |             continue; | 
 | 2461 |         } | 
 | 2462 |         i++; | 
 | 2463 |     } | 
 | 2464 |     for (size_t i = 0; i  < mAvailableInputDevices.size();) { | 
 | 2465 |         if (mAvailableInputDevices[i]->mId == 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2466 |             ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2467 |             mAvailableInputDevices.remove(mAvailableInputDevices[i]); | 
 | 2468 |             continue; | 
 | 2469 |         } | 
 | 2470 |         i++; | 
 | 2471 |     } | 
 | 2472 |     // make sure default device is reachable | 
 | 2473 |     if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2474 |         ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2475 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2476 |  | 
 | 2477 |     ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); | 
 | 2478 |  | 
 | 2479 |     updateDevicesAndOutputs(); | 
 | 2480 |  | 
 | 2481 | #ifdef AUDIO_POLICY_TEST | 
 | 2482 |     if (mPrimaryOutput != 0) { | 
 | 2483 |         AudioParameter outputCmd = AudioParameter(); | 
 | 2484 |         outputCmd.addInt(String8("set_id"), 0); | 
 | 2485 |         mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); | 
 | 2486 |  | 
 | 2487 |         mTestDevice = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 2488 |         mTestSamplingRate = 44100; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2489 |         mTestFormat = AUDIO_FORMAT_PCM_16_BIT; | 
 | 2490 |         mTestChannels =  AUDIO_CHANNEL_OUT_STEREO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2491 |         mTestLatencyMs = 0; | 
 | 2492 |         mCurOutput = 0; | 
 | 2493 |         mDirectOutput = false; | 
 | 2494 |         for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { | 
 | 2495 |             mTestOutputs[i] = 0; | 
 | 2496 |         } | 
 | 2497 |  | 
 | 2498 |         const size_t SIZE = 256; | 
 | 2499 |         char buffer[SIZE]; | 
 | 2500 |         snprintf(buffer, SIZE, "AudioPolicyManagerTest"); | 
 | 2501 |         run(buffer, ANDROID_PRIORITY_AUDIO); | 
 | 2502 |     } | 
 | 2503 | #endif //AUDIO_POLICY_TEST | 
 | 2504 | } | 
 | 2505 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2506 | AudioPolicyManager::~AudioPolicyManager() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2507 | { | 
 | 2508 | #ifdef AUDIO_POLICY_TEST | 
 | 2509 |     exit(); | 
 | 2510 | #endif //AUDIO_POLICY_TEST | 
 | 2511 |    for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2512 |         mpClientInterface->closeOutput(mOutputs.keyAt(i)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2513 |    } | 
 | 2514 |    for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 2515 |         mpClientInterface->closeInput(mInputs.keyAt(i)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2516 |    } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2517 |    mAvailableOutputDevices.clear(); | 
 | 2518 |    mAvailableInputDevices.clear(); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2519 |    mOutputs.clear(); | 
 | 2520 |    mInputs.clear(); | 
 | 2521 |    mHwModules.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2522 | } | 
 | 2523 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2524 | status_t AudioPolicyManager::initCheck() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2525 | { | 
 | 2526 |     return (mPrimaryOutput == 0) ? NO_INIT : NO_ERROR; | 
 | 2527 | } | 
 | 2528 |  | 
 | 2529 | #ifdef AUDIO_POLICY_TEST | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2530 | bool AudioPolicyManager::threadLoop() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2531 | { | 
 | 2532 |     ALOGV("entering threadLoop()"); | 
 | 2533 |     while (!exitPending()) | 
 | 2534 |     { | 
 | 2535 |         String8 command; | 
 | 2536 |         int valueInt; | 
 | 2537 |         String8 value; | 
 | 2538 |  | 
 | 2539 |         Mutex::Autolock _l(mLock); | 
 | 2540 |         mWaitWorkCV.waitRelative(mLock, milliseconds(50)); | 
 | 2541 |  | 
 | 2542 |         command = mpClientInterface->getParameters(0, String8("test_cmd_policy")); | 
 | 2543 |         AudioParameter param = AudioParameter(command); | 
 | 2544 |  | 
 | 2545 |         if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR && | 
 | 2546 |             valueInt != 0) { | 
 | 2547 |             ALOGV("Test command %s received", command.string()); | 
 | 2548 |             String8 target; | 
 | 2549 |             if (param.get(String8("target"), target) != NO_ERROR) { | 
 | 2550 |                 target = "Manager"; | 
 | 2551 |             } | 
 | 2552 |             if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) { | 
 | 2553 |                 param.remove(String8("test_cmd_policy_output")); | 
 | 2554 |                 mCurOutput = valueInt; | 
 | 2555 |             } | 
 | 2556 |             if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) { | 
 | 2557 |                 param.remove(String8("test_cmd_policy_direct")); | 
 | 2558 |                 if (value == "false") { | 
 | 2559 |                     mDirectOutput = false; | 
 | 2560 |                 } else if (value == "true") { | 
 | 2561 |                     mDirectOutput = true; | 
 | 2562 |                 } | 
 | 2563 |             } | 
 | 2564 |             if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) { | 
 | 2565 |                 param.remove(String8("test_cmd_policy_input")); | 
 | 2566 |                 mTestInput = valueInt; | 
 | 2567 |             } | 
 | 2568 |  | 
 | 2569 |             if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) { | 
 | 2570 |                 param.remove(String8("test_cmd_policy_format")); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2571 |                 int format = AUDIO_FORMAT_INVALID; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2572 |                 if (value == "PCM 16 bits") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2573 |                     format = AUDIO_FORMAT_PCM_16_BIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2574 |                 } else if (value == "PCM 8 bits") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2575 |                     format = AUDIO_FORMAT_PCM_8_BIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2576 |                 } else if (value == "Compressed MP3") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2577 |                     format = AUDIO_FORMAT_MP3; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2578 |                 } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2579 |                 if (format != AUDIO_FORMAT_INVALID) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2580 |                     if (target == "Manager") { | 
 | 2581 |                         mTestFormat = format; | 
 | 2582 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 2583 |                         AudioParameter outputParam = AudioParameter(); | 
 | 2584 |                         outputParam.addInt(String8("format"), format); | 
 | 2585 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 2586 |                     } | 
 | 2587 |                 } | 
 | 2588 |             } | 
 | 2589 |             if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) { | 
 | 2590 |                 param.remove(String8("test_cmd_policy_channels")); | 
 | 2591 |                 int channels = 0; | 
 | 2592 |  | 
 | 2593 |                 if (value == "Channels Stereo") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2594 |                     channels =  AUDIO_CHANNEL_OUT_STEREO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2595 |                 } else if (value == "Channels Mono") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2596 |                     channels =  AUDIO_CHANNEL_OUT_MONO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2597 |                 } | 
 | 2598 |                 if (channels != 0) { | 
 | 2599 |                     if (target == "Manager") { | 
 | 2600 |                         mTestChannels = channels; | 
 | 2601 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 2602 |                         AudioParameter outputParam = AudioParameter(); | 
 | 2603 |                         outputParam.addInt(String8("channels"), channels); | 
 | 2604 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 2605 |                     } | 
 | 2606 |                 } | 
 | 2607 |             } | 
 | 2608 |             if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) { | 
 | 2609 |                 param.remove(String8("test_cmd_policy_sampleRate")); | 
 | 2610 |                 if (valueInt >= 0 && valueInt <= 96000) { | 
 | 2611 |                     int samplingRate = valueInt; | 
 | 2612 |                     if (target == "Manager") { | 
 | 2613 |                         mTestSamplingRate = samplingRate; | 
 | 2614 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 2615 |                         AudioParameter outputParam = AudioParameter(); | 
 | 2616 |                         outputParam.addInt(String8("sampling_rate"), samplingRate); | 
 | 2617 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 2618 |                     } | 
 | 2619 |                 } | 
 | 2620 |             } | 
 | 2621 |  | 
 | 2622 |             if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) { | 
 | 2623 |                 param.remove(String8("test_cmd_policy_reopen")); | 
 | 2624 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2625 |                 sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2626 |                 mpClientInterface->closeOutput(mPrimaryOutput); | 
 | 2627 |  | 
 | 2628 |                 audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle; | 
 | 2629 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2630 |                 mOutputs.removeItem(mPrimaryOutput); | 
 | 2631 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2632 |                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2633 |                 outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2634 |                 audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 2635 |                 config.sample_rate = outputDesc->mSamplingRate; | 
 | 2636 |                 config.channel_mask = outputDesc->mChannelMask; | 
 | 2637 |                 config.format = outputDesc->mFormat; | 
 | 2638 |                 status_t status = mpClientInterface->openOutput(moduleHandle, | 
 | 2639 |                                                                 &mPrimaryOutput, | 
 | 2640 |                                                                 &config, | 
 | 2641 |                                                                 &outputDesc->mDevice, | 
 | 2642 |                                                                 String8(""), | 
 | 2643 |                                                                 &outputDesc->mLatency, | 
 | 2644 |                                                                 outputDesc->mFlags); | 
 | 2645 |                 if (status != NO_ERROR) { | 
 | 2646 |                     ALOGE("Failed to reopen hardware output stream, " | 
 | 2647 |                         "samplingRate: %d, format %d, channels %d", | 
 | 2648 |                         outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannelMask); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2649 |                 } else { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2650 |                     outputDesc->mSamplingRate = config.sample_rate; | 
 | 2651 |                     outputDesc->mChannelMask = config.channel_mask; | 
 | 2652 |                     outputDesc->mFormat = config.format; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2653 |                     AudioParameter outputCmd = AudioParameter(); | 
 | 2654 |                     outputCmd.addInt(String8("set_id"), 0); | 
 | 2655 |                     mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); | 
 | 2656 |                     addOutput(mPrimaryOutput, outputDesc); | 
 | 2657 |                 } | 
 | 2658 |             } | 
 | 2659 |  | 
 | 2660 |  | 
 | 2661 |             mpClientInterface->setParameters(0, String8("test_cmd_policy=")); | 
 | 2662 |         } | 
 | 2663 |     } | 
 | 2664 |     return false; | 
 | 2665 | } | 
 | 2666 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2667 | void AudioPolicyManager::exit() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2668 | { | 
 | 2669 |     { | 
 | 2670 |         AutoMutex _l(mLock); | 
 | 2671 |         requestExit(); | 
 | 2672 |         mWaitWorkCV.signal(); | 
 | 2673 |     } | 
 | 2674 |     requestExitAndWait(); | 
 | 2675 | } | 
 | 2676 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2677 | int AudioPolicyManager::testOutputIndex(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2678 | { | 
 | 2679 |     for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { | 
 | 2680 |         if (output == mTestOutputs[i]) return i; | 
 | 2681 |     } | 
 | 2682 |     return 0; | 
 | 2683 | } | 
 | 2684 | #endif //AUDIO_POLICY_TEST | 
 | 2685 |  | 
 | 2686 | // --- | 
 | 2687 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2688 | void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2689 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2690 |     outputDesc->mIoHandle = output; | 
 | 2691 |     outputDesc->mId = nextUniqueId(); | 
 | 2692 |     mOutputs.add(output, outputDesc); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2693 |     nextAudioPortGeneration(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2694 | } | 
 | 2695 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2696 | void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc) | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2697 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2698 |     inputDesc->mIoHandle = input; | 
 | 2699 |     inputDesc->mId = nextUniqueId(); | 
 | 2700 |     mInputs.add(input, inputDesc); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2701 |     nextAudioPortGeneration(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2702 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2703 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2704 | void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/, | 
 | 2705 |         const String8 address /*in*/, | 
 | 2706 |         SortedVector<audio_io_handle_t>& outputs /*out*/) { | 
 | 2707 |     // look for a match on the given address on the addresses of the outputs: | 
 | 2708 |     // find the address by finding the patch that maps to this output | 
 | 2709 |     ssize_t patchIdx = mAudioPatches.indexOfKey(desc->mPatchHandle); | 
 | 2710 |     //ALOGV("    inspecting output %d (patch %d) for supported device=0x%x", | 
 | 2711 |     //        outputIdx, patchIdx,  desc->mProfile->mSupportedDevices.types()); | 
 | 2712 |     if (patchIdx >= 0) { | 
 | 2713 |         const sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patchIdx); | 
 | 2714 |         const int numSinks = patchDesc->mPatch.num_sinks; | 
 | 2715 |         for (ssize_t j=0; j < numSinks; j++) { | 
 | 2716 |             if (patchDesc->mPatch.sinks[j].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2717 |                 const char* patchAddr = | 
 | 2718 |                         patchDesc->mPatch.sinks[j].ext.device.address; | 
 | 2719 |                 if (strncmp(patchAddr, | 
 | 2720 |                         address.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) { | 
 | 2721 |                     ALOGV("checkOutputsForDevice(): adding opened output %d on same address %s", | 
 | 2722 |                             desc->mIoHandle,  patchDesc->mPatch.sinks[j].ext.device.address); | 
 | 2723 |                     outputs.add(desc->mIoHandle); | 
 | 2724 |                     break; | 
 | 2725 |                 } | 
 | 2726 |             } | 
 | 2727 |         } | 
 | 2728 |     } | 
 | 2729 | } | 
 | 2730 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2731 | status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2732 |                                                        audio_policy_dev_state_t state, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2733 |                                                        SortedVector<audio_io_handle_t>& outputs, | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2734 |                                                        const String8 address) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2735 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2736 |     sp<AudioOutputDescriptor> desc; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2737 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2738 |     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2739 |         // first list already open outputs that can be routed to this device | 
 | 2740 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2741 |             desc = mOutputs.valueAt(i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2742 |             if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2743 |                 if (!deviceDistinguishesOnAddress(device)) { | 
 | 2744 |                     ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i)); | 
 | 2745 |                     outputs.add(mOutputs.keyAt(i)); | 
 | 2746 |                 } else { | 
 | 2747 |                     ALOGV("  checking address match due to device 0x%x", device); | 
 | 2748 |                     findIoHandlesByAddress(desc, address, outputs); | 
 | 2749 |                 } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2750 |             } | 
 | 2751 |         } | 
 | 2752 |         // then look for output profiles that can be routed to this device | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2753 |         SortedVector< sp<IOProfile> > profiles; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2754 |         for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 2755 |         { | 
 | 2756 |             if (mHwModules[i]->mHandle == 0) { | 
 | 2757 |                 continue; | 
 | 2758 |             } | 
 | 2759 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2760 |             { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2761 |                 if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2762 |                     ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2763 |                     profiles.add(mHwModules[i]->mOutputProfiles[j]); | 
 | 2764 |                 } | 
 | 2765 |             } | 
 | 2766 |         } | 
 | 2767 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2768 |         ALOGV("  found %d profiles, %d outputs", profiles.size(), outputs.size()); | 
 | 2769 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2770 |         if (profiles.isEmpty() && outputs.isEmpty()) { | 
 | 2771 |             ALOGW("checkOutputsForDevice(): No output available for device %04x", device); | 
 | 2772 |             return BAD_VALUE; | 
 | 2773 |         } | 
 | 2774 |  | 
 | 2775 |         // open outputs for matching profiles if needed. Direct outputs are also opened to | 
 | 2776 |         // query for dynamic parameters and will be closed later by setDeviceConnectionState() | 
 | 2777 |         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] | 2778 |             sp<IOProfile> profile = profiles[profile_index]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2779 |  | 
 | 2780 |             // nothing to do if one output is already opened for this profile | 
 | 2781 |             size_t j; | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2782 |             for (j = 0; j < outputs.size(); j++) { | 
 | 2783 |                 desc = mOutputs.valueFor(outputs.itemAt(j)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2784 |                 if (!desc->isDuplicated() && desc->mProfile == profile) { | 
 | 2785 |                     break; | 
 | 2786 |                 } | 
 | 2787 |             } | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2788 |             if (j != outputs.size()) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2789 |                 continue; | 
 | 2790 |             } | 
 | 2791 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2792 |             ALOGV("opening output for device %08x with params %s profile %p", | 
 | 2793 |                                                       device, address.string(), profile.get()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2794 |             desc = new AudioOutputDescriptor(profile); | 
 | 2795 |             desc->mDevice = device; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2796 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 2797 |             config.sample_rate = desc->mSamplingRate; | 
 | 2798 |             config.channel_mask = desc->mChannelMask; | 
 | 2799 |             config.format = desc->mFormat; | 
 | 2800 |             config.offload_info.sample_rate = desc->mSamplingRate; | 
 | 2801 |             config.offload_info.channel_mask = desc->mChannelMask; | 
 | 2802 |             config.offload_info.format = desc->mFormat; | 
 | 2803 |             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; | 
 | 2804 |             status_t status = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 2805 |                                                             &output, | 
 | 2806 |                                                             &config, | 
 | 2807 |                                                             &desc->mDevice, | 
 | 2808 |                                                             address, | 
 | 2809 |                                                             &desc->mLatency, | 
 | 2810 |                                                             desc->mFlags); | 
 | 2811 |             if (status == NO_ERROR) { | 
 | 2812 |                 desc->mSamplingRate = config.sample_rate; | 
 | 2813 |                 desc->mChannelMask = config.channel_mask; | 
 | 2814 |                 desc->mFormat = config.format; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2815 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2816 |                 // Here is where the out_set_parameters() for card & device gets called | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2817 |                 if (!address.isEmpty()) { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2818 |                     char *param = audio_device_address_to_parameter(device, address); | 
 | 2819 |                     mpClientInterface->setParameters(output, String8(param)); | 
 | 2820 |                     free(param); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2821 |                 } | 
 | 2822 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2823 |                 // Here is where we step through and resolve any "dynamic" fields | 
 | 2824 |                 String8 reply; | 
 | 2825 |                 char *value; | 
 | 2826 |                 if (profile->mSamplingRates[0] == 0) { | 
 | 2827 |                     reply = mpClientInterface->getParameters(output, | 
 | 2828 |                                             String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2829 |                     ALOGV("checkOutputsForDevice() supported sampling rates %s", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2830 |                               reply.string()); | 
 | 2831 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2832 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2833 |                         profile->loadSamplingRates(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2834 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2835 |                 } | 
 | 2836 |                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 2837 |                     reply = mpClientInterface->getParameters(output, | 
 | 2838 |                                                    String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2839 |                     ALOGV("checkOutputsForDevice() supported formats %s", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2840 |                               reply.string()); | 
 | 2841 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2842 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2843 |                         profile->loadFormats(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2844 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2845 |                 } | 
 | 2846 |                 if (profile->mChannelMasks[0] == 0) { | 
 | 2847 |                     reply = mpClientInterface->getParameters(output, | 
 | 2848 |                                                   String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2849 |                     ALOGV("checkOutputsForDevice() supported channel masks %s", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2850 |                               reply.string()); | 
 | 2851 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2852 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2853 |                         profile->loadOutChannels(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2854 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2855 |                 } | 
 | 2856 |                 if (((profile->mSamplingRates[0] == 0) && | 
 | 2857 |                          (profile->mSamplingRates.size() < 2)) || | 
 | 2858 |                      ((profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) && | 
 | 2859 |                          (profile->mFormats.size() < 2)) || | 
 | 2860 |                      ((profile->mChannelMasks[0] == 0) && | 
 | 2861 |                          (profile->mChannelMasks.size() < 2))) { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2862 |                     ALOGW("checkOutputsForDevice() missing param"); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2863 |                     mpClientInterface->closeOutput(output); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2864 |                     output = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 2865 |                 } else if (profile->mSamplingRates[0] == 0 || profile->mFormats[0] == 0 || | 
 | 2866 |                             profile->mChannelMasks[0] == 0) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2867 |                     mpClientInterface->closeOutput(output); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2868 |                     config.sample_rate = profile->pickSamplingRate(); | 
 | 2869 |                     config.channel_mask = profile->pickChannelMask(); | 
 | 2870 |                     config.format = profile->pickFormat(); | 
 | 2871 |                     config.offload_info.sample_rate = config.sample_rate; | 
 | 2872 |                     config.offload_info.channel_mask = config.channel_mask; | 
 | 2873 |                     config.offload_info.format = config.format; | 
 | 2874 |                     status = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 2875 |                                                            &output, | 
 | 2876 |                                                            &config, | 
 | 2877 |                                                            &desc->mDevice, | 
 | 2878 |                                                            address, | 
 | 2879 |                                                            &desc->mLatency, | 
 | 2880 |                                                            desc->mFlags); | 
 | 2881 |                     if (status == NO_ERROR) { | 
 | 2882 |                         desc->mSamplingRate = config.sample_rate; | 
 | 2883 |                         desc->mChannelMask = config.channel_mask; | 
 | 2884 |                         desc->mFormat = config.format; | 
 | 2885 |                     } else { | 
 | 2886 |                         output = AUDIO_IO_HANDLE_NONE; | 
 | 2887 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2888 |                 } | 
 | 2889 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2890 |                 if (output != AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2891 |                     addOutput(output, desc); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2892 |                     if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2893 |                         audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2894 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2895 |                         // set initial stream volume for device | 
 | 2896 |                         applyStreamVolumes(output, device, 0, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2897 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2898 |                         //TODO: configure audio effect output stage here | 
 | 2899 |  | 
 | 2900 |                         // open a duplicating output thread for the new output and the primary output | 
 | 2901 |                         duplicatedOutput = mpClientInterface->openDuplicateOutput(output, | 
 | 2902 |                                                                                   mPrimaryOutput); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2903 |                         if (duplicatedOutput != AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2904 |                             // add duplicated output descriptor | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2905 |                             sp<AudioOutputDescriptor> dupOutputDesc = | 
 | 2906 |                                     new AudioOutputDescriptor(NULL); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2907 |                             dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput); | 
 | 2908 |                             dupOutputDesc->mOutput2 = mOutputs.valueFor(output); | 
 | 2909 |                             dupOutputDesc->mSamplingRate = desc->mSamplingRate; | 
 | 2910 |                             dupOutputDesc->mFormat = desc->mFormat; | 
 | 2911 |                             dupOutputDesc->mChannelMask = desc->mChannelMask; | 
 | 2912 |                             dupOutputDesc->mLatency = desc->mLatency; | 
 | 2913 |                             addOutput(duplicatedOutput, dupOutputDesc); | 
 | 2914 |                             applyStreamVolumes(duplicatedOutput, device, 0, true); | 
 | 2915 |                         } else { | 
 | 2916 |                             ALOGW("checkOutputsForDevice() could not open dup output for %d and %d", | 
 | 2917 |                                     mPrimaryOutput, output); | 
 | 2918 |                             mpClientInterface->closeOutput(output); | 
 | 2919 |                             mOutputs.removeItem(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2920 |                             nextAudioPortGeneration(); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2921 |                             output = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2922 |                         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2923 |                     } | 
 | 2924 |                 } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2925 |             } else { | 
 | 2926 |                 output = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2927 |             } | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 2928 |             if (output == AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2929 |                 ALOGW("checkOutputsForDevice() could not open output for device %x", device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2930 |                 profiles.removeAt(profile_index); | 
 | 2931 |                 profile_index--; | 
 | 2932 |             } else { | 
 | 2933 |                 outputs.add(output); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2934 |                 if (deviceDistinguishesOnAddress(device)) { | 
 | 2935 |                     ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)", | 
 | 2936 |                             device, address.string()); | 
 | 2937 |                     setOutputDevice(output, device, true/*force*/, 0/*delay*/, | 
 | 2938 |                             NULL/*patch handle*/, address.string()); | 
 | 2939 |                 } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2940 |                 ALOGV("checkOutputsForDevice(): adding output %d", output); | 
 | 2941 |             } | 
 | 2942 |         } | 
 | 2943 |  | 
 | 2944 |         if (profiles.isEmpty()) { | 
 | 2945 |             ALOGW("checkOutputsForDevice(): No output available for device %04x", device); | 
 | 2946 |             return BAD_VALUE; | 
 | 2947 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2948 |     } else { // Disconnect | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2949 |         // check if one opened output is not needed any more after disconnecting one device | 
 | 2950 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2951 |             desc = mOutputs.valueAt(i); | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 2952 |             if (!desc->isDuplicated()) { | 
 | 2953 |                 if  (!(desc->mProfile->mSupportedDevices.types() | 
 | 2954 |                         & mAvailableOutputDevices.types())) { | 
 | 2955 |                     ALOGV("checkOutputsForDevice(): disconnecting adding output %d", | 
 | 2956 |                             mOutputs.keyAt(i)); | 
 | 2957 |                     outputs.add(mOutputs.keyAt(i)); | 
 | 2958 |                 } else if (deviceDistinguishesOnAddress(device) && | 
 | 2959 |                         // exact match on device | 
 | 2960 |                         (desc->mProfile->mSupportedDevices.types() == device)) { | 
 | 2961 |                     findIoHandlesByAddress(desc, address, outputs); | 
 | 2962 |                 } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2963 |             } | 
 | 2964 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2965 |         // Clear any profiles associated with the disconnected device. | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2966 |         for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 2967 |         { | 
 | 2968 |             if (mHwModules[i]->mHandle == 0) { | 
 | 2969 |                 continue; | 
 | 2970 |             } | 
 | 2971 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2972 |             { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2973 |                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2974 |                 if (profile->mSupportedDevices.types() & device) { | 
 | 2975 |                     ALOGV("checkOutputsForDevice(): " | 
 | 2976 |                             "clearing direct output profile %zu on module %zu", j, i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2977 |                     if (profile->mSamplingRates[0] == 0) { | 
 | 2978 |                         profile->mSamplingRates.clear(); | 
 | 2979 |                         profile->mSamplingRates.add(0); | 
 | 2980 |                     } | 
 | 2981 |                     if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 2982 |                         profile->mFormats.clear(); | 
 | 2983 |                         profile->mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 2984 |                     } | 
 | 2985 |                     if (profile->mChannelMasks[0] == 0) { | 
 | 2986 |                         profile->mChannelMasks.clear(); | 
 | 2987 |                         profile->mChannelMasks.add(0); | 
 | 2988 |                     } | 
 | 2989 |                 } | 
 | 2990 |             } | 
 | 2991 |         } | 
 | 2992 |     } | 
 | 2993 |     return NO_ERROR; | 
 | 2994 | } | 
 | 2995 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2996 | status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device, | 
 | 2997 |                                                       audio_policy_dev_state_t state, | 
 | 2998 |                                                       SortedVector<audio_io_handle_t>& inputs, | 
 | 2999 |                                                       const String8 address) | 
 | 3000 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3001 |     sp<AudioInputDescriptor> desc; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3002 |     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { | 
 | 3003 |         // first list already open inputs that can be routed to this device | 
 | 3004 |         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3005 |             desc = mInputs.valueAt(input_index); | 
 | 3006 |             if (desc->mProfile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) { | 
 | 3007 |                 ALOGV("checkInputsForDevice(): adding opened input %d", mInputs.keyAt(input_index)); | 
 | 3008 |                inputs.add(mInputs.keyAt(input_index)); | 
 | 3009 |             } | 
 | 3010 |         } | 
 | 3011 |  | 
 | 3012 |         // then look for input profiles that can be routed to this device | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3013 |         SortedVector< sp<IOProfile> > profiles; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3014 |         for (size_t module_idx = 0; module_idx < mHwModules.size(); module_idx++) | 
 | 3015 |         { | 
 | 3016 |             if (mHwModules[module_idx]->mHandle == 0) { | 
 | 3017 |                 continue; | 
 | 3018 |             } | 
 | 3019 |             for (size_t profile_index = 0; | 
 | 3020 |                  profile_index < mHwModules[module_idx]->mInputProfiles.size(); | 
 | 3021 |                  profile_index++) | 
 | 3022 |             { | 
 | 3023 |                 if (mHwModules[module_idx]->mInputProfiles[profile_index]->mSupportedDevices.types() | 
 | 3024 |                         & (device & ~AUDIO_DEVICE_BIT_IN)) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 3025 |                     ALOGV("checkInputsForDevice(): adding profile %zu from module %zu", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3026 |                           profile_index, module_idx); | 
 | 3027 |                     profiles.add(mHwModules[module_idx]->mInputProfiles[profile_index]); | 
 | 3028 |                 } | 
 | 3029 |             } | 
 | 3030 |         } | 
 | 3031 |  | 
 | 3032 |         if (profiles.isEmpty() && inputs.isEmpty()) { | 
 | 3033 |             ALOGW("checkInputsForDevice(): No input available for device 0x%X", device); | 
 | 3034 |             return BAD_VALUE; | 
 | 3035 |         } | 
 | 3036 |  | 
 | 3037 |         // open inputs for matching profiles if needed. Direct inputs are also opened to | 
 | 3038 |         // query for dynamic parameters and will be closed later by setDeviceConnectionState() | 
 | 3039 |         for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) { | 
 | 3040 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3041 |             sp<IOProfile> profile = profiles[profile_index]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3042 |             // nothing to do if one input is already opened for this profile | 
 | 3043 |             size_t input_index; | 
 | 3044 |             for (input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3045 |                 desc = mInputs.valueAt(input_index); | 
 | 3046 |                 if (desc->mProfile == profile) { | 
 | 3047 |                     break; | 
 | 3048 |                 } | 
 | 3049 |             } | 
 | 3050 |             if (input_index != mInputs.size()) { | 
 | 3051 |                 continue; | 
 | 3052 |             } | 
 | 3053 |  | 
 | 3054 |             ALOGV("opening input for device 0x%X with params %s", device, address.string()); | 
 | 3055 |             desc = new AudioInputDescriptor(profile); | 
 | 3056 |             desc->mDevice = device; | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3057 |             audio_config_t config = AUDIO_CONFIG_INITIALIZER; | 
 | 3058 |             config.sample_rate = desc->mSamplingRate; | 
 | 3059 |             config.channel_mask = desc->mChannelMask; | 
 | 3060 |             config.format = desc->mFormat; | 
 | 3061 |             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; | 
 | 3062 |             status_t status = mpClientInterface->openInput(profile->mModule->mHandle, | 
 | 3063 |                                                            &input, | 
 | 3064 |                                                            &config, | 
 | 3065 |                                                            &desc->mDevice, | 
 | 3066 |                                                            address, | 
 | 3067 |                                                            AUDIO_SOURCE_MIC, | 
 | 3068 |                                                            AUDIO_INPUT_FLAG_NONE /*FIXME*/); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3069 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3070 |             if (status == NO_ERROR) { | 
 | 3071 |                 desc->mSamplingRate = config.sample_rate; | 
 | 3072 |                 desc->mChannelMask = config.channel_mask; | 
 | 3073 |                 desc->mFormat = config.format; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3074 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3075 |                 if (!address.isEmpty()) { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3076 |                     char *param = audio_device_address_to_parameter(device, address); | 
 | 3077 |                     mpClientInterface->setParameters(input, String8(param)); | 
 | 3078 |                     free(param); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3079 |                 } | 
 | 3080 |  | 
 | 3081 |                 // Here is where we step through and resolve any "dynamic" fields | 
 | 3082 |                 String8 reply; | 
 | 3083 |                 char *value; | 
 | 3084 |                 if (profile->mSamplingRates[0] == 0) { | 
 | 3085 |                     reply = mpClientInterface->getParameters(input, | 
 | 3086 |                                             String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); | 
 | 3087 |                     ALOGV("checkInputsForDevice() direct input sup sampling rates %s", | 
 | 3088 |                               reply.string()); | 
 | 3089 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3090 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3091 |                         profile->loadSamplingRates(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3092 |                     } | 
 | 3093 |                 } | 
 | 3094 |                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3095 |                     reply = mpClientInterface->getParameters(input, | 
 | 3096 |                                                    String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); | 
 | 3097 |                     ALOGV("checkInputsForDevice() direct input sup formats %s", reply.string()); | 
 | 3098 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3099 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3100 |                         profile->loadFormats(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3101 |                     } | 
 | 3102 |                 } | 
 | 3103 |                 if (profile->mChannelMasks[0] == 0) { | 
 | 3104 |                     reply = mpClientInterface->getParameters(input, | 
 | 3105 |                                                   String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); | 
 | 3106 |                     ALOGV("checkInputsForDevice() direct input sup channel masks %s", | 
 | 3107 |                               reply.string()); | 
 | 3108 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 3109 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3110 |                         profile->loadInChannels(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3111 |                     } | 
 | 3112 |                 } | 
 | 3113 |                 if (((profile->mSamplingRates[0] == 0) && (profile->mSamplingRates.size() < 2)) || | 
 | 3114 |                      ((profile->mFormats[0] == 0) && (profile->mFormats.size() < 2)) || | 
 | 3115 |                      ((profile->mChannelMasks[0] == 0) && (profile->mChannelMasks.size() < 2))) { | 
 | 3116 |                     ALOGW("checkInputsForDevice() direct input missing param"); | 
 | 3117 |                     mpClientInterface->closeInput(input); | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3118 |                     input = AUDIO_IO_HANDLE_NONE; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3119 |                 } | 
 | 3120 |  | 
 | 3121 |                 if (input != 0) { | 
 | 3122 |                     addInput(input, desc); | 
 | 3123 |                 } | 
 | 3124 |             } // endif input != 0 | 
 | 3125 |  | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 3126 |             if (input == AUDIO_IO_HANDLE_NONE) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3127 |                 ALOGW("checkInputsForDevice() could not open input for device 0x%X", device); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3128 |                 profiles.removeAt(profile_index); | 
 | 3129 |                 profile_index--; | 
 | 3130 |             } else { | 
 | 3131 |                 inputs.add(input); | 
 | 3132 |                 ALOGV("checkInputsForDevice(): adding input %d", input); | 
 | 3133 |             } | 
 | 3134 |         } // end scan profiles | 
 | 3135 |  | 
 | 3136 |         if (profiles.isEmpty()) { | 
 | 3137 |             ALOGW("checkInputsForDevice(): No input available for device 0x%X", device); | 
 | 3138 |             return BAD_VALUE; | 
 | 3139 |         } | 
 | 3140 |     } else { | 
 | 3141 |         // Disconnect | 
 | 3142 |         // check if one opened input is not needed any more after disconnecting one device | 
 | 3143 |         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3144 |             desc = mInputs.valueAt(input_index); | 
 | 3145 |             if (!(desc->mProfile->mSupportedDevices.types() & mAvailableInputDevices.types())) { | 
 | 3146 |                 ALOGV("checkInputsForDevice(): disconnecting adding input %d", | 
 | 3147 |                       mInputs.keyAt(input_index)); | 
 | 3148 |                 inputs.add(mInputs.keyAt(input_index)); | 
 | 3149 |             } | 
 | 3150 |         } | 
 | 3151 |         // Clear any profiles associated with the disconnected device. | 
 | 3152 |         for (size_t module_index = 0; module_index < mHwModules.size(); module_index++) { | 
 | 3153 |             if (mHwModules[module_index]->mHandle == 0) { | 
 | 3154 |                 continue; | 
 | 3155 |             } | 
 | 3156 |             for (size_t profile_index = 0; | 
 | 3157 |                  profile_index < mHwModules[module_index]->mInputProfiles.size(); | 
 | 3158 |                  profile_index++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3159 |                 sp<IOProfile> profile = mHwModules[module_index]->mInputProfiles[profile_index]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3160 |                 if (profile->mSupportedDevices.types() & device) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 3161 |                     ALOGV("checkInputsForDevice(): clearing direct input profile %zu on module %zu", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3162 |                           profile_index, module_index); | 
 | 3163 |                     if (profile->mSamplingRates[0] == 0) { | 
 | 3164 |                         profile->mSamplingRates.clear(); | 
 | 3165 |                         profile->mSamplingRates.add(0); | 
 | 3166 |                     } | 
 | 3167 |                     if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3168 |                         profile->mFormats.clear(); | 
 | 3169 |                         profile->mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 3170 |                     } | 
 | 3171 |                     if (profile->mChannelMasks[0] == 0) { | 
 | 3172 |                         profile->mChannelMasks.clear(); | 
 | 3173 |                         profile->mChannelMasks.add(0); | 
 | 3174 |                     } | 
 | 3175 |                 } | 
 | 3176 |             } | 
 | 3177 |         } | 
 | 3178 |     } // end disconnect | 
 | 3179 |  | 
 | 3180 |     return NO_ERROR; | 
 | 3181 | } | 
 | 3182 |  | 
 | 3183 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3184 | void AudioPolicyManager::closeOutput(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3185 | { | 
 | 3186 |     ALOGV("closeOutput(%d)", output); | 
 | 3187 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3188 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3189 |     if (outputDesc == NULL) { | 
 | 3190 |         ALOGW("closeOutput() unknown output %d", output); | 
 | 3191 |         return; | 
 | 3192 |     } | 
 | 3193 |  | 
 | 3194 |     // look for duplicated outputs connected to the output being removed. | 
 | 3195 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3196 |         sp<AudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3197 |         if (dupOutputDesc->isDuplicated() && | 
 | 3198 |                 (dupOutputDesc->mOutput1 == outputDesc || | 
 | 3199 |                 dupOutputDesc->mOutput2 == outputDesc)) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3200 |             sp<AudioOutputDescriptor> outputDesc2; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3201 |             if (dupOutputDesc->mOutput1 == outputDesc) { | 
 | 3202 |                 outputDesc2 = dupOutputDesc->mOutput2; | 
 | 3203 |             } else { | 
 | 3204 |                 outputDesc2 = dupOutputDesc->mOutput1; | 
 | 3205 |             } | 
 | 3206 |             // As all active tracks on duplicated output will be deleted, | 
 | 3207 |             // and as they were also referenced on the other output, the reference | 
 | 3208 |             // count for their stream type must be adjusted accordingly on | 
 | 3209 |             // the other output. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3210 |             for (int j = 0; j < AUDIO_STREAM_CNT; j++) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3211 |                 int refCount = dupOutputDesc->mRefCount[j]; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3212 |                 outputDesc2->changeRefCount((audio_stream_type_t)j,-refCount); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3213 |             } | 
 | 3214 |             audio_io_handle_t duplicatedOutput = mOutputs.keyAt(i); | 
 | 3215 |             ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput); | 
 | 3216 |  | 
 | 3217 |             mpClientInterface->closeOutput(duplicatedOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3218 |             mOutputs.removeItem(duplicatedOutput); | 
 | 3219 |         } | 
 | 3220 |     } | 
 | 3221 |  | 
 | 3222 |     AudioParameter param; | 
 | 3223 |     param.add(String8("closing"), String8("true")); | 
 | 3224 |     mpClientInterface->setParameters(output, param.toString()); | 
 | 3225 |  | 
 | 3226 |     mpClientInterface->closeOutput(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3227 |     mOutputs.removeItem(output); | 
 | 3228 |     mPreviousOutputs = mOutputs; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3229 |     nextAudioPortGeneration(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3230 | } | 
 | 3231 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3232 | SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device, | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3233 |                         DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3234 | { | 
 | 3235 |     SortedVector<audio_io_handle_t> outputs; | 
 | 3236 |  | 
 | 3237 |     ALOGVV("getOutputsForDevice() device %04x", device); | 
 | 3238 |     for (size_t i = 0; i < openOutputs.size(); i++) { | 
 | 3239 |         ALOGVV("output %d isDuplicated=%d device=%04x", | 
 | 3240 |                 i, openOutputs.valueAt(i)->isDuplicated(), openOutputs.valueAt(i)->supportedDevices()); | 
 | 3241 |         if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) { | 
 | 3242 |             ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i)); | 
 | 3243 |             outputs.add(openOutputs.keyAt(i)); | 
 | 3244 |         } | 
 | 3245 |     } | 
 | 3246 |     return outputs; | 
 | 3247 | } | 
 | 3248 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3249 | bool AudioPolicyManager::vectorsEqual(SortedVector<audio_io_handle_t>& outputs1, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3250 |                                    SortedVector<audio_io_handle_t>& outputs2) | 
 | 3251 | { | 
 | 3252 |     if (outputs1.size() != outputs2.size()) { | 
 | 3253 |         return false; | 
 | 3254 |     } | 
 | 3255 |     for (size_t i = 0; i < outputs1.size(); i++) { | 
 | 3256 |         if (outputs1[i] != outputs2[i]) { | 
 | 3257 |             return false; | 
 | 3258 |         } | 
 | 3259 |     } | 
 | 3260 |     return true; | 
 | 3261 | } | 
 | 3262 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3263 | void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3264 | { | 
 | 3265 |     audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/); | 
 | 3266 |     audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 3267 |     SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs); | 
 | 3268 |     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs); | 
 | 3269 |  | 
 | 3270 |     if (!vectorsEqual(srcOutputs,dstOutputs)) { | 
 | 3271 |         ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d", | 
 | 3272 |               strategy, srcOutputs[0], dstOutputs[0]); | 
 | 3273 |         // mute strategy while moving tracks from one output to another | 
 | 3274 |         for (size_t i = 0; i < srcOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3275 |             sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3276 |             if (desc->isStrategyActive(strategy)) { | 
 | 3277 |                 setStrategyMute(strategy, true, srcOutputs[i]); | 
 | 3278 |                 setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); | 
 | 3279 |             } | 
 | 3280 |         } | 
 | 3281 |  | 
 | 3282 |         // Move effects associated to this strategy from previous output to new output | 
 | 3283 |         if (strategy == STRATEGY_MEDIA) { | 
 | 3284 |             audio_io_handle_t fxOutput = selectOutputForEffects(dstOutputs); | 
 | 3285 |             SortedVector<audio_io_handle_t> moved; | 
 | 3286 |             for (size_t i = 0; i < mEffects.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3287 |                 sp<EffectDescriptor> effectDesc = mEffects.valueAt(i); | 
 | 3288 |                 if (effectDesc->mSession == AUDIO_SESSION_OUTPUT_MIX && | 
 | 3289 |                         effectDesc->mIo != fxOutput) { | 
 | 3290 |                     if (moved.indexOf(effectDesc->mIo) < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3291 |                         ALOGV("checkOutputForStrategy() moving effect %d to output %d", | 
 | 3292 |                               mEffects.keyAt(i), fxOutput); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3293 |                         mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, effectDesc->mIo, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3294 |                                                        fxOutput); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3295 |                         moved.add(effectDesc->mIo); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3296 |                     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3297 |                     effectDesc->mIo = fxOutput; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3298 |                 } | 
 | 3299 |             } | 
 | 3300 |         } | 
 | 3301 |         // Move tracks associated to this strategy from previous output to new output | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3302 |         for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
 | 3303 |             if (getStrategy((audio_stream_type_t)i) == strategy) { | 
 | 3304 |                 mpClientInterface->invalidateStream((audio_stream_type_t)i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3305 |             } | 
 | 3306 |         } | 
 | 3307 |     } | 
 | 3308 | } | 
 | 3309 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3310 | void AudioPolicyManager::checkOutputForAllStrategies() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3311 | { | 
 | 3312 |     checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE); | 
 | 3313 |     checkOutputForStrategy(STRATEGY_PHONE); | 
 | 3314 |     checkOutputForStrategy(STRATEGY_SONIFICATION); | 
 | 3315 |     checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 3316 |     checkOutputForStrategy(STRATEGY_MEDIA); | 
 | 3317 |     checkOutputForStrategy(STRATEGY_DTMF); | 
 | 3318 | } | 
 | 3319 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3320 | audio_io_handle_t AudioPolicyManager::getA2dpOutput() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3321 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3322 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3323 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3324 |         if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { | 
 | 3325 |             return mOutputs.keyAt(i); | 
 | 3326 |         } | 
 | 3327 |     } | 
 | 3328 |  | 
 | 3329 |     return 0; | 
 | 3330 | } | 
 | 3331 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3332 | void AudioPolicyManager::checkA2dpSuspend() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3333 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3334 |     audio_io_handle_t a2dpOutput = getA2dpOutput(); | 
 | 3335 |     if (a2dpOutput == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3336 |         mA2dpSuspended = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3337 |         return; | 
 | 3338 |     } | 
 | 3339 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3340 |     bool isScoConnected = | 
 | 3341 |             (mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3342 |     // suspend A2DP output if: | 
 | 3343 |     //      (NOT already suspended) && | 
 | 3344 |     //      ((SCO device is connected && | 
 | 3345 |     //       (forced usage for communication || for record is SCO))) || | 
 | 3346 |     //      (phone state is ringing || in call) | 
 | 3347 |     // | 
 | 3348 |     // restore A2DP output if: | 
 | 3349 |     //      (Already suspended) && | 
 | 3350 |     //      ((SCO device is NOT connected || | 
 | 3351 |     //       (forced usage NOT for communication && NOT for record is SCO))) && | 
 | 3352 |     //      (phone state is NOT ringing && NOT in call) | 
 | 3353 |     // | 
 | 3354 |     if (mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3355 |         if ((!isScoConnected || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3356 |              ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO) && | 
 | 3357 |               (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] != AUDIO_POLICY_FORCE_BT_SCO))) && | 
 | 3358 |              ((mPhoneState != AUDIO_MODE_IN_CALL) && | 
 | 3359 |               (mPhoneState != AUDIO_MODE_RINGTONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3360 |  | 
 | 3361 |             mpClientInterface->restoreOutput(a2dpOutput); | 
 | 3362 |             mA2dpSuspended = false; | 
 | 3363 |         } | 
 | 3364 |     } else { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3365 |         if ((isScoConnected && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3366 |              ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) || | 
 | 3367 |               (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO))) || | 
 | 3368 |              ((mPhoneState == AUDIO_MODE_IN_CALL) || | 
 | 3369 |               (mPhoneState == AUDIO_MODE_RINGTONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3370 |  | 
 | 3371 |             mpClientInterface->suspendOutput(a2dpOutput); | 
 | 3372 |             mA2dpSuspended = true; | 
 | 3373 |         } | 
 | 3374 |     } | 
 | 3375 | } | 
 | 3376 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3377 | audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, bool fromCache) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3378 | { | 
 | 3379 |     audio_devices_t device = AUDIO_DEVICE_NONE; | 
 | 3380 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3381 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3382 |  | 
 | 3383 |     ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3384 |     if (index >= 0) { | 
 | 3385 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3386 |         if (patchDesc->mUid != mUidCached) { | 
 | 3387 |             ALOGV("getNewOutputDevice() device %08x forced by patch %d", | 
 | 3388 |                   outputDesc->device(), outputDesc->mPatchHandle); | 
 | 3389 |             return outputDesc->device(); | 
 | 3390 |         } | 
 | 3391 |     } | 
 | 3392 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3393 |     // check the following by order of priority to request a routing change if necessary: | 
 | 3394 |     // 1: the strategy enforced audible is active on the output: | 
 | 3395 |     //      use device for strategy enforced audible | 
 | 3396 |     // 2: we are in call or the strategy phone is active on the output: | 
 | 3397 |     //      use device for strategy phone | 
 | 3398 |     // 3: the strategy sonification is active on the output: | 
 | 3399 |     //      use device for strategy sonification | 
 | 3400 |     // 4: the strategy "respectful" sonification is active on the output: | 
 | 3401 |     //      use device for strategy "respectful" sonification | 
 | 3402 |     // 5: the strategy media is active on the output: | 
 | 3403 |     //      use device for strategy media | 
 | 3404 |     // 6: the strategy DTMF is active on the output: | 
 | 3405 |     //      use device for strategy DTMF | 
 | 3406 |     if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) { | 
 | 3407 |         device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache); | 
 | 3408 |     } else if (isInCall() || | 
 | 3409 |                     outputDesc->isStrategyActive(STRATEGY_PHONE)) { | 
 | 3410 |         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache); | 
 | 3411 |     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) { | 
 | 3412 |         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache); | 
 | 3413 |     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) { | 
 | 3414 |         device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache); | 
 | 3415 |     } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) { | 
 | 3416 |         device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache); | 
 | 3417 |     } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) { | 
 | 3418 |         device = getDeviceForStrategy(STRATEGY_DTMF, fromCache); | 
 | 3419 |     } | 
 | 3420 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3421 |     ALOGV("getNewOutputDevice() selected device %x", device); | 
 | 3422 |     return device; | 
 | 3423 | } | 
 | 3424 |  | 
 | 3425 | audio_devices_t AudioPolicyManager::getNewInputDevice(audio_io_handle_t input) | 
 | 3426 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3427 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3428 |  | 
 | 3429 |     ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 3430 |     if (index >= 0) { | 
 | 3431 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3432 |         if (patchDesc->mUid != mUidCached) { | 
 | 3433 |             ALOGV("getNewInputDevice() device %08x forced by patch %d", | 
 | 3434 |                   inputDesc->mDevice, inputDesc->mPatchHandle); | 
 | 3435 |             return inputDesc->mDevice; | 
 | 3436 |         } | 
 | 3437 |     } | 
 | 3438 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3439 |     audio_devices_t device = getDeviceForInputSource(inputDesc->mInputSource); | 
 | 3440 |  | 
 | 3441 |     ALOGV("getNewInputDevice() selected device %x", device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3442 |     return device; | 
 | 3443 | } | 
 | 3444 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3445 | uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3446 |     return (uint32_t)getStrategy(stream); | 
 | 3447 | } | 
 | 3448 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3449 | audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3450 |     // By checking the range of stream before calling getStrategy, we avoid | 
 | 3451 |     // getStrategy's behavior for invalid streams.  getStrategy would do a ALOGE | 
 | 3452 |     // and then return STRATEGY_MEDIA, but we want to return the empty set. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3453 |     if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_CNT) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3454 |         return AUDIO_DEVICE_NONE; | 
 | 3455 |     } | 
 | 3456 |     audio_devices_t devices; | 
 | 3457 |     AudioPolicyManager::routing_strategy strategy = getStrategy(stream); | 
 | 3458 |     devices = getDeviceForStrategy(strategy, true /*fromCache*/); | 
 | 3459 |     SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs); | 
 | 3460 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3461 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3462 |         if (outputDesc->isStrategyActive(strategy)) { | 
 | 3463 |             devices = outputDesc->device(); | 
 | 3464 |             break; | 
 | 3465 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3466 |     } | 
 | 3467 |     return devices; | 
 | 3468 | } | 
 | 3469 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3470 | AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3471 |         audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3472 |     // stream to strategy mapping | 
 | 3473 |     switch (stream) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3474 |     case AUDIO_STREAM_VOICE_CALL: | 
 | 3475 |     case AUDIO_STREAM_BLUETOOTH_SCO: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3476 |         return STRATEGY_PHONE; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3477 |     case AUDIO_STREAM_RING: | 
 | 3478 |     case AUDIO_STREAM_ALARM: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3479 |         return STRATEGY_SONIFICATION; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3480 |     case AUDIO_STREAM_NOTIFICATION: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3481 |         return STRATEGY_SONIFICATION_RESPECTFUL; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3482 |     case AUDIO_STREAM_DTMF: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3483 |         return STRATEGY_DTMF; | 
 | 3484 |     default: | 
 | 3485 |         ALOGE("unknown stream type"); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3486 |     case AUDIO_STREAM_SYSTEM: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3487 |         // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs | 
 | 3488 |         // while key clicks are played produces a poor result | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3489 |     case AUDIO_STREAM_TTS: | 
 | 3490 |     case AUDIO_STREAM_MUSIC: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3491 |         return STRATEGY_MEDIA; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3492 |     case AUDIO_STREAM_ENFORCED_AUDIBLE: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3493 |         return STRATEGY_ENFORCED_AUDIBLE; | 
 | 3494 |     } | 
 | 3495 | } | 
 | 3496 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 3497 | uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) { | 
 | 3498 |     // flags to strategy mapping | 
 | 3499 |     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { | 
 | 3500 |         return (uint32_t) STRATEGY_ENFORCED_AUDIBLE; | 
 | 3501 |     } | 
 | 3502 |  | 
 | 3503 |     // usage to strategy mapping | 
 | 3504 |     switch (attr->usage) { | 
 | 3505 |     case AUDIO_USAGE_MEDIA: | 
 | 3506 |     case AUDIO_USAGE_GAME: | 
 | 3507 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
 | 3508 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 3509 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 3510 |         return (uint32_t) STRATEGY_MEDIA; | 
 | 3511 |  | 
 | 3512 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 3513 |         return (uint32_t) STRATEGY_PHONE; | 
 | 3514 |  | 
 | 3515 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 3516 |         return (uint32_t) STRATEGY_DTMF; | 
 | 3517 |  | 
 | 3518 |     case AUDIO_USAGE_ALARM: | 
 | 3519 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 3520 |         return (uint32_t) STRATEGY_SONIFICATION; | 
 | 3521 |  | 
 | 3522 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 3523 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 3524 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 3525 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 3526 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 3527 |         return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL; | 
 | 3528 |  | 
 | 3529 |     case AUDIO_USAGE_UNKNOWN: | 
 | 3530 |     default: | 
 | 3531 |         return (uint32_t) STRATEGY_MEDIA; | 
 | 3532 |     } | 
 | 3533 | } | 
 | 3534 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3535 | void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3536 |     switch(stream) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3537 |     case AUDIO_STREAM_MUSIC: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3538 |         checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 3539 |         updateDevicesAndOutputs(); | 
 | 3540 |         break; | 
 | 3541 |     default: | 
 | 3542 |         break; | 
 | 3543 |     } | 
 | 3544 | } | 
 | 3545 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3546 | audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3547 |                                                              bool fromCache) | 
 | 3548 | { | 
 | 3549 |     uint32_t device = AUDIO_DEVICE_NONE; | 
 | 3550 |  | 
 | 3551 |     if (fromCache) { | 
 | 3552 |         ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x", | 
 | 3553 |               strategy, mDeviceForStrategy[strategy]); | 
 | 3554 |         return mDeviceForStrategy[strategy]; | 
 | 3555 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3556 |     audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3557 |     switch (strategy) { | 
 | 3558 |  | 
 | 3559 |     case STRATEGY_SONIFICATION_RESPECTFUL: | 
 | 3560 |         if (isInCall()) { | 
 | 3561 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3562 |         } else if (isStreamActiveRemotely(AUDIO_STREAM_MUSIC, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3563 |                 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { | 
 | 3564 |             // while media is playing on a remote device, use the the sonification behavior. | 
 | 3565 |             // Note that we test this usecase before testing if media is playing because | 
 | 3566 |             //   the isStreamActive() method only informs about the activity of a stream, not | 
 | 3567 |             //   if it's for local playback. Note also that we use the same delay between both tests | 
 | 3568 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3569 |         } else if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3570 |             // while media is playing (or has recently played), use the same device | 
 | 3571 |             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); | 
 | 3572 |         } else { | 
 | 3573 |             // when media is not playing anymore, fall back on the sonification behavior | 
 | 3574 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
 | 3575 |         } | 
 | 3576 |  | 
 | 3577 |         break; | 
 | 3578 |  | 
 | 3579 |     case STRATEGY_DTMF: | 
 | 3580 |         if (!isInCall()) { | 
 | 3581 |             // when off call, DTMF strategy follows the same rules as MEDIA strategy | 
 | 3582 |             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); | 
 | 3583 |             break; | 
 | 3584 |         } | 
 | 3585 |         // when in call, DTMF and PHONE strategies follow the same rules | 
 | 3586 |         // FALL THROUGH | 
 | 3587 |  | 
 | 3588 |     case STRATEGY_PHONE: | 
 | 3589 |         // for phone strategy, we first consider the forced use and then the available devices by order | 
 | 3590 |         // of priority | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3591 |         switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) { | 
 | 3592 |         case AUDIO_POLICY_FORCE_BT_SCO: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3593 |             if (!isInCall() || strategy != STRATEGY_DTMF) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3594 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3595 |                 if (device) break; | 
 | 3596 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3597 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3598 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3599 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3600 |             if (device) break; | 
 | 3601 |             // if SCO device is requested but no SCO device is available, fall back to default case | 
 | 3602 |             // FALL THROUGH | 
 | 3603 |  | 
 | 3604 |         default:    // FORCE_NONE | 
 | 3605 |             // 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] | 3606 |             if (!isInCall() && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3607 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3608 |                     (getA2dpOutput() != 0) && !mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3609 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3610 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3611 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3612 |                 if (device) break; | 
 | 3613 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3614 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3615 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3616 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3617 |             if (device) break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3618 |             if (mPhoneState != AUDIO_MODE_IN_CALL) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3619 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3620 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3621 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3622 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3623 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3624 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3625 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3626 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3627 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3628 |                 if (device) break; | 
 | 3629 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3630 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3631 |             if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3632 |             device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3633 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 3634 |                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE"); | 
 | 3635 |             } | 
 | 3636 |             break; | 
 | 3637 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3638 |         case AUDIO_POLICY_FORCE_SPEAKER: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3639 |             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to | 
 | 3640 |             // A2DP speaker when forcing to speaker output | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3641 |             if (!isInCall() && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3642 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3643 |                     (getA2dpOutput() != 0) && !mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3644 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3645 |                 if (device) break; | 
 | 3646 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3647 |             if (mPhoneState != AUDIO_MODE_IN_CALL) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3648 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3649 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3650 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3651 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3652 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3653 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3654 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3655 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3656 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3657 |                 if (device) break; | 
 | 3658 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3659 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3660 |             if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3661 |             device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3662 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 3663 |                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER"); | 
 | 3664 |             } | 
 | 3665 |             break; | 
 | 3666 |         } | 
 | 3667 |     break; | 
 | 3668 |  | 
 | 3669 |     case STRATEGY_SONIFICATION: | 
 | 3670 |  | 
 | 3671 |         // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by | 
 | 3672 |         // handleIncallSonification(). | 
 | 3673 |         if (isInCall()) { | 
 | 3674 |             device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/); | 
 | 3675 |             break; | 
 | 3676 |         } | 
 | 3677 |         // FALL THROUGH | 
 | 3678 |  | 
 | 3679 |     case STRATEGY_ENFORCED_AUDIBLE: | 
 | 3680 |         // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION | 
 | 3681 |         // except: | 
 | 3682 |         //   - when in call where it doesn't default to STRATEGY_PHONE behavior | 
 | 3683 |         //   - in countries where not enforced in which case it follows STRATEGY_MEDIA | 
 | 3684 |  | 
 | 3685 |         if ((strategy == STRATEGY_SONIFICATION) || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3686 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3687 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3688 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 3689 |                 ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION"); | 
 | 3690 |             } | 
 | 3691 |         } | 
 | 3692 |         // The second device used for sonification is the same as the device used by media strategy | 
 | 3693 |         // FALL THROUGH | 
 | 3694 |  | 
 | 3695 |     case STRATEGY_MEDIA: { | 
 | 3696 |         uint32_t device2 = AUDIO_DEVICE_NONE; | 
 | 3697 |         if (strategy != STRATEGY_SONIFICATION) { | 
 | 3698 |             // no sonification on remote submix (e.g. WFD) | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3699 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3700 |         } | 
 | 3701 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3702 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3703 |                 (getA2dpOutput() != 0) && !mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3704 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3705 |             if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3706 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3707 |             } | 
 | 3708 |             if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3709 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3710 |             } | 
 | 3711 |         } | 
 | 3712 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3713 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3714 |         } | 
 | 3715 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3716 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3717 |         } | 
 | 3718 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3719 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3720 |         } | 
 | 3721 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3722 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3723 |         } | 
 | 3724 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3725 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3726 |         } | 
 | 3727 |         if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { | 
 | 3728 |             // no sonification on aux digital (e.g. HDMI) | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3729 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3730 |         } | 
 | 3731 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3732 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3733 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3734 |         } | 
 | 3735 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3736 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3737 |         } | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3738 |         int device3 = AUDIO_DEVICE_NONE; | 
 | 3739 |         if (strategy == STRATEGY_MEDIA) { | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 3740 |             // ARC, SPDIF and AUX_LINE can co-exist with others. | 
| Jungshik Jang | 0c94309 | 2014-07-08 22:11:24 +0900 | [diff] [blame] | 3741 |             device3 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_HDMI_ARC; | 
 | 3742 |             device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPDIF); | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 3743 |             device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_LINE); | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3744 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3745 |  | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3746 |         device2 |= device3; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3747 |         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or | 
 | 3748 |         // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise | 
 | 3749 |         device |= device2; | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3750 |  | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 3751 |         // If hdmi system audio mode is on, remove speaker out of output list. | 
 | 3752 |         if ((strategy == STRATEGY_MEDIA) && | 
 | 3753 |             (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] == | 
 | 3754 |                 AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { | 
 | 3755 |             device &= ~AUDIO_DEVICE_OUT_SPEAKER; | 
 | 3756 |         } | 
 | 3757 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3758 |         if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3759 |         device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3760 |         if (device == AUDIO_DEVICE_NONE) { | 
 | 3761 |             ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA"); | 
 | 3762 |         } | 
 | 3763 |         } break; | 
 | 3764 |  | 
 | 3765 |     default: | 
 | 3766 |         ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); | 
 | 3767 |         break; | 
 | 3768 |     } | 
 | 3769 |  | 
 | 3770 |     ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); | 
 | 3771 |     return device; | 
 | 3772 | } | 
 | 3773 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3774 | void AudioPolicyManager::updateDevicesAndOutputs() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3775 | { | 
 | 3776 |     for (int i = 0; i < NUM_STRATEGIES; i++) { | 
 | 3777 |         mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); | 
 | 3778 |     } | 
 | 3779 |     mPreviousOutputs = mOutputs; | 
 | 3780 | } | 
 | 3781 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3782 | uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> outputDesc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3783 |                                                        audio_devices_t prevDevice, | 
 | 3784 |                                                        uint32_t delayMs) | 
 | 3785 | { | 
 | 3786 |     // mute/unmute strategies using an incompatible device combination | 
 | 3787 |     // if muting, wait for the audio in pcm buffer to be drained before proceeding | 
 | 3788 |     // if unmuting, unmute only after the specified delay | 
 | 3789 |     if (outputDesc->isDuplicated()) { | 
 | 3790 |         return 0; | 
 | 3791 |     } | 
 | 3792 |  | 
 | 3793 |     uint32_t muteWaitMs = 0; | 
 | 3794 |     audio_devices_t device = outputDesc->device(); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3795 |     bool shouldMute = outputDesc->isActive() && (popcount(device) >= 2); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3796 |  | 
 | 3797 |     for (size_t i = 0; i < NUM_STRATEGIES; i++) { | 
 | 3798 |         audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); | 
 | 3799 |         bool mute = shouldMute && (curDevice & device) && (curDevice != device); | 
 | 3800 |         bool doMute = false; | 
 | 3801 |  | 
 | 3802 |         if (mute && !outputDesc->mStrategyMutedByDevice[i]) { | 
 | 3803 |             doMute = true; | 
 | 3804 |             outputDesc->mStrategyMutedByDevice[i] = true; | 
 | 3805 |         } else if (!mute && outputDesc->mStrategyMutedByDevice[i]){ | 
 | 3806 |             doMute = true; | 
 | 3807 |             outputDesc->mStrategyMutedByDevice[i] = false; | 
 | 3808 |         } | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3809 |         if (doMute) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3810 |             for (size_t j = 0; j < mOutputs.size(); j++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3811 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(j); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3812 |                 // skip output if it does not share any device with current output | 
 | 3813 |                 if ((desc->supportedDevices() & outputDesc->supportedDevices()) | 
 | 3814 |                         == AUDIO_DEVICE_NONE) { | 
 | 3815 |                     continue; | 
 | 3816 |                 } | 
 | 3817 |                 audio_io_handle_t curOutput = mOutputs.keyAt(j); | 
 | 3818 |                 ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d", | 
 | 3819 |                       mute ? "muting" : "unmuting", i, curDevice, curOutput); | 
 | 3820 |                 setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs); | 
 | 3821 |                 if (desc->isStrategyActive((routing_strategy)i)) { | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3822 |                     if (mute) { | 
 | 3823 |                         // FIXME: should not need to double latency if volume could be applied | 
 | 3824 |                         // immediately by the audioflinger mixer. We must account for the delay | 
 | 3825 |                         // between now and the next time the audioflinger thread for this output | 
 | 3826 |                         // will process a buffer (which corresponds to one buffer size, | 
 | 3827 |                         // usually 1/2 or 1/4 of the latency). | 
 | 3828 |                         if (muteWaitMs < desc->latency() * 2) { | 
 | 3829 |                             muteWaitMs = desc->latency() * 2; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3830 |                         } | 
 | 3831 |                     } | 
 | 3832 |                 } | 
 | 3833 |             } | 
 | 3834 |         } | 
 | 3835 |     } | 
 | 3836 |  | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3837 |     // temporary mute output if device selection changes to avoid volume bursts due to | 
 | 3838 |     // different per device volumes | 
 | 3839 |     if (outputDesc->isActive() && (device != prevDevice)) { | 
 | 3840 |         if (muteWaitMs < outputDesc->latency() * 2) { | 
 | 3841 |             muteWaitMs = outputDesc->latency() * 2; | 
 | 3842 |         } | 
 | 3843 |         for (size_t i = 0; i < NUM_STRATEGIES; i++) { | 
 | 3844 |             if (outputDesc->isStrategyActive((routing_strategy)i)) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3845 |                 setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle); | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3846 |                 // do tempMute unmute after twice the mute wait time | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3847 |                 setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle, | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3848 |                                 muteWaitMs *2, device); | 
 | 3849 |             } | 
 | 3850 |         } | 
 | 3851 |     } | 
 | 3852 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3853 |     // wait for the PCM output buffers to empty before proceeding with the rest of the command | 
 | 3854 |     if (muteWaitMs > delayMs) { | 
 | 3855 |         muteWaitMs -= delayMs; | 
 | 3856 |         usleep(muteWaitMs * 1000); | 
 | 3857 |         return muteWaitMs; | 
 | 3858 |     } | 
 | 3859 |     return 0; | 
 | 3860 | } | 
 | 3861 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3862 | uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3863 |                                              audio_devices_t device, | 
 | 3864 |                                              bool force, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3865 |                                              int delayMs, | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3866 |                                              audio_patch_handle_t *patchHandle, | 
 | 3867 |                                              const char* address) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3868 | { | 
 | 3869 |     ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3870 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3871 |     AudioParameter param; | 
 | 3872 |     uint32_t muteWaitMs; | 
 | 3873 |  | 
 | 3874 |     if (outputDesc->isDuplicated()) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3875 |         muteWaitMs = setOutputDevice(outputDesc->mOutput1->mIoHandle, device, force, delayMs); | 
 | 3876 |         muteWaitMs += setOutputDevice(outputDesc->mOutput2->mIoHandle, device, force, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3877 |         return muteWaitMs; | 
 | 3878 |     } | 
 | 3879 |     // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current | 
 | 3880 |     // output profile | 
 | 3881 |     if ((device != AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3882 |             ((device & outputDesc->mProfile->mSupportedDevices.types()) == 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3883 |         return 0; | 
 | 3884 |     } | 
 | 3885 |  | 
 | 3886 |     // filter devices according to output selected | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3887 |     device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3888 |  | 
 | 3889 |     audio_devices_t prevDevice = outputDesc->mDevice; | 
 | 3890 |  | 
 | 3891 |     ALOGV("setOutputDevice() prevDevice %04x", prevDevice); | 
 | 3892 |  | 
 | 3893 |     if (device != AUDIO_DEVICE_NONE) { | 
 | 3894 |         outputDesc->mDevice = device; | 
 | 3895 |     } | 
 | 3896 |     muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs); | 
 | 3897 |  | 
 | 3898 |     // Do not change the routing if: | 
 | 3899 |     //  - the requested device is AUDIO_DEVICE_NONE | 
 | 3900 |     //  - the requested device is the same as current device and force is not specified. | 
 | 3901 |     // Doing this check here allows the caller to call setOutputDevice() without conditions | 
 | 3902 |     if ((device == AUDIO_DEVICE_NONE || device == prevDevice) && !force) { | 
 | 3903 |         ALOGV("setOutputDevice() setting same device %04x or null device for output %d", device, output); | 
 | 3904 |         return muteWaitMs; | 
 | 3905 |     } | 
 | 3906 |  | 
 | 3907 |     ALOGV("setOutputDevice() changing device"); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3908 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3909 |     // do the routing | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3910 |     if (device == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3911 |         resetOutputDevice(output, delayMs, NULL); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3912 |     } else { | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 3913 |         DeviceVector deviceList = (address == NULL) ? | 
 | 3914 |                 mAvailableOutputDevices.getDevicesFromType(device) | 
 | 3915 |                 : mAvailableOutputDevices.getDevicesFromTypeAddr(device, String8(address)); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3916 |         if (!deviceList.isEmpty()) { | 
 | 3917 |             struct audio_patch patch; | 
 | 3918 |             outputDesc->toAudioPortConfig(&patch.sources[0]); | 
 | 3919 |             patch.num_sources = 1; | 
 | 3920 |             patch.num_sinks = 0; | 
 | 3921 |             for (size_t i = 0; i < deviceList.size() && i < AUDIO_PATCH_PORTS_MAX; i++) { | 
 | 3922 |                 deviceList.itemAt(i)->toAudioPortConfig(&patch.sinks[i]); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3923 |                 patch.num_sinks++; | 
 | 3924 |             } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3925 |             ssize_t index; | 
 | 3926 |             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) { | 
 | 3927 |                 index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 3928 |             } else { | 
 | 3929 |                 index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3930 |             } | 
 | 3931 |             sp< AudioPatch> patchDesc; | 
 | 3932 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 3933 |             if (index >= 0) { | 
 | 3934 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 3935 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 3936 |             } | 
 | 3937 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3938 |             status_t status = mpClientInterface->createAudioPatch(&patch, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3939 |                                                                    &afPatchHandle, | 
 | 3940 |                                                                    delayMs); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3941 |             ALOGV("setOutputDevice() createAudioPatch returned %d patchHandle %d" | 
 | 3942 |                     "num_sources %d num_sinks %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3943 |                                        status, afPatchHandle, patch.num_sources, patch.num_sinks); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3944 |             if (status == NO_ERROR) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3945 |                 if (index < 0) { | 
 | 3946 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 3947 |                                                &patch, mUidCached); | 
 | 3948 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 3949 |                 } else { | 
 | 3950 |                     patchDesc->mPatch = patch; | 
 | 3951 |                 } | 
 | 3952 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 3953 |                 patchDesc->mUid = mUidCached; | 
 | 3954 |                 if (patchHandle) { | 
 | 3955 |                     *patchHandle = patchDesc->mHandle; | 
 | 3956 |                 } | 
 | 3957 |                 outputDesc->mPatchHandle = patchDesc->mHandle; | 
 | 3958 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 3959 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3960 |             } | 
 | 3961 |         } | 
 | 3962 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3963 |  | 
 | 3964 |     // update stream volumes according to new device | 
 | 3965 |     applyStreamVolumes(output, device, delayMs); | 
 | 3966 |  | 
 | 3967 |     return muteWaitMs; | 
 | 3968 | } | 
 | 3969 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3970 | status_t AudioPolicyManager::resetOutputDevice(audio_io_handle_t output, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3971 |                                                int delayMs, | 
 | 3972 |                                                audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3973 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3974 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3975 |     ssize_t index; | 
 | 3976 |     if (patchHandle) { | 
 | 3977 |         index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 3978 |     } else { | 
 | 3979 |         index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3980 |     } | 
 | 3981 |     if (index < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3982 |         return INVALID_OPERATION; | 
 | 3983 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3984 |     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3985 |     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3986 |     ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status); | 
 | 3987 |     outputDesc->mPatchHandle = 0; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3988 |     removeAudioPatch(patchDesc->mHandle); | 
 | 3989 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 3990 |     mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3991 |     return status; | 
 | 3992 | } | 
 | 3993 |  | 
 | 3994 | status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input, | 
 | 3995 |                                             audio_devices_t device, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3996 |                                             bool force, | 
 | 3997 |                                             audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3998 | { | 
 | 3999 |     status_t status = NO_ERROR; | 
 | 4000 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4001 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4002 |     if ((device != AUDIO_DEVICE_NONE) && ((device != inputDesc->mDevice) || force)) { | 
 | 4003 |         inputDesc->mDevice = device; | 
 | 4004 |  | 
 | 4005 |         DeviceVector deviceList = mAvailableInputDevices.getDevicesFromType(device); | 
 | 4006 |         if (!deviceList.isEmpty()) { | 
 | 4007 |             struct audio_patch patch; | 
 | 4008 |             inputDesc->toAudioPortConfig(&patch.sinks[0]); | 
| Eric Laurent | daf92cc | 2014-07-22 15:36:10 -0700 | [diff] [blame] | 4009 |             // AUDIO_SOURCE_HOTWORD is for internal use only: | 
 | 4010 |             // handled as AUDIO_SOURCE_VOICE_RECOGNITION by the audio HAL | 
 | 4011 |             if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD) { | 
 | 4012 |                 patch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_VOICE_RECOGNITION; | 
 | 4013 |             } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4014 |             patch.num_sinks = 1; | 
 | 4015 |             //only one input device for now | 
 | 4016 |             deviceList.itemAt(0)->toAudioPortConfig(&patch.sources[0]); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4017 |             patch.num_sources = 1; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4018 |             ssize_t index; | 
 | 4019 |             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) { | 
 | 4020 |                 index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 4021 |             } else { | 
 | 4022 |                 index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 4023 |             } | 
 | 4024 |             sp< AudioPatch> patchDesc; | 
 | 4025 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 4026 |             if (index >= 0) { | 
 | 4027 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 4028 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 4029 |             } | 
 | 4030 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4031 |             status_t status = mpClientInterface->createAudioPatch(&patch, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4032 |                                                                   &afPatchHandle, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4033 |                                                                   0); | 
 | 4034 |             ALOGV("setInputDevice() createAudioPatch returned %d patchHandle %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4035 |                                                                           status, afPatchHandle); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4036 |             if (status == NO_ERROR) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4037 |                 if (index < 0) { | 
 | 4038 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 4039 |                                                &patch, mUidCached); | 
 | 4040 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 4041 |                 } else { | 
 | 4042 |                     patchDesc->mPatch = patch; | 
 | 4043 |                 } | 
 | 4044 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 4045 |                 patchDesc->mUid = mUidCached; | 
 | 4046 |                 if (patchHandle) { | 
 | 4047 |                     *patchHandle = patchDesc->mHandle; | 
 | 4048 |                 } | 
 | 4049 |                 inputDesc->mPatchHandle = patchDesc->mHandle; | 
 | 4050 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 4051 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4052 |             } | 
 | 4053 |         } | 
 | 4054 |     } | 
 | 4055 |     return status; | 
 | 4056 | } | 
 | 4057 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4058 | status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input, | 
 | 4059 |                                               audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4060 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4061 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4062 |     ssize_t index; | 
 | 4063 |     if (patchHandle) { | 
 | 4064 |         index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 4065 |     } else { | 
 | 4066 |         index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 4067 |     } | 
 | 4068 |     if (index < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4069 |         return INVALID_OPERATION; | 
 | 4070 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4071 |     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 4072 |     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4073 |     ALOGV("resetInputDevice() releaseAudioPatch returned %d", status); | 
 | 4074 |     inputDesc->mPatchHandle = 0; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4075 |     removeAudioPatch(patchDesc->mHandle); | 
 | 4076 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 4077 |     mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4078 |     return status; | 
 | 4079 | } | 
 | 4080 |  | 
 | 4081 | sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 4082 |                                                    uint32_t& samplingRate, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4083 |                                                    audio_format_t format, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 4084 |                                                    audio_channel_mask_t channelMask, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 4085 |                                                    audio_input_flags_t flags) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4086 | { | 
 | 4087 |     // Choose an input profile based on the requested capture parameters: select the first available | 
 | 4088 |     // profile supporting all requested parameters. | 
 | 4089 |  | 
 | 4090 |     for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 4091 |     { | 
 | 4092 |         if (mHwModules[i]->mHandle == 0) { | 
 | 4093 |             continue; | 
 | 4094 |         } | 
 | 4095 |         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) | 
 | 4096 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4097 |             sp<IOProfile> profile = mHwModules[i]->mInputProfiles[j]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 4098 |             // profile->log(); | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 4099 |             if (profile->isCompatibleProfile(device, samplingRate, | 
 | 4100 |                                              &samplingRate /*updatedSamplingRate*/, | 
 | 4101 |                                              format, channelMask, (audio_output_flags_t) flags)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4102 |                 return profile; | 
 | 4103 |             } | 
 | 4104 |         } | 
 | 4105 |     } | 
 | 4106 |     return NULL; | 
 | 4107 | } | 
 | 4108 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4109 | audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4110 | { | 
 | 4111 |     uint32_t device = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4112 |     audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & | 
 | 4113 |                                             ~AUDIO_DEVICE_BIT_IN; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4114 |     switch (inputSource) { | 
 | 4115 |     case AUDIO_SOURCE_VOICE_UPLINK: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4116 |       if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4117 |           device = AUDIO_DEVICE_IN_VOICE_CALL; | 
 | 4118 |           break; | 
 | 4119 |       } | 
 | 4120 |       // FALL THROUGH | 
 | 4121 |  | 
 | 4122 |     case AUDIO_SOURCE_DEFAULT: | 
 | 4123 |     case AUDIO_SOURCE_MIC: | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 4124 |     if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) { | 
 | 4125 |         device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP; | 
 | 4126 |         break; | 
 | 4127 |     } | 
 | 4128 |     // FALL THROUGH | 
 | 4129 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4130 |     case AUDIO_SOURCE_VOICE_RECOGNITION: | 
 | 4131 |     case AUDIO_SOURCE_HOTWORD: | 
 | 4132 |     case AUDIO_SOURCE_VOICE_COMMUNICATION: | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4133 |         if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4134 |                 availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4135 |             device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4136 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4137 |             device = AUDIO_DEVICE_IN_WIRED_HEADSET; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 4138 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { | 
 | 4139 |             device = AUDIO_DEVICE_IN_USB_DEVICE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4140 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4141 |             device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 4142 |         } | 
 | 4143 |         break; | 
 | 4144 |     case AUDIO_SOURCE_CAMCORDER: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4145 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4146 |             device = AUDIO_DEVICE_IN_BACK_MIC; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4147 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4148 |             device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 4149 |         } | 
 | 4150 |         break; | 
 | 4151 |     case AUDIO_SOURCE_VOICE_DOWNLINK: | 
 | 4152 |     case AUDIO_SOURCE_VOICE_CALL: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4153 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4154 |             device = AUDIO_DEVICE_IN_VOICE_CALL; | 
 | 4155 |         } | 
 | 4156 |         break; | 
 | 4157 |     case AUDIO_SOURCE_REMOTE_SUBMIX: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4158 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4159 |             device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; | 
 | 4160 |         } | 
 | 4161 |         break; | 
 | 4162 |     default: | 
 | 4163 |         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource); | 
 | 4164 |         break; | 
 | 4165 |     } | 
 | 4166 |     ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); | 
 | 4167 |     return device; | 
 | 4168 | } | 
 | 4169 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4170 | bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4171 | { | 
 | 4172 |     if ((device & AUDIO_DEVICE_BIT_IN) != 0) { | 
 | 4173 |         device &= ~AUDIO_DEVICE_BIT_IN; | 
 | 4174 |         if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0)) | 
 | 4175 |             return true; | 
 | 4176 |     } | 
 | 4177 |     return false; | 
 | 4178 | } | 
 | 4179 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 4180 | bool AudioPolicyManager::deviceDistinguishesOnAddress(audio_devices_t device) { | 
 | 4181 |     return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL) != 0); | 
 | 4182 | } | 
 | 4183 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4184 | audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4185 | { | 
 | 4186 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4187 |         const sp<AudioInputDescriptor>  input_descriptor = mInputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4188 |         if ((input_descriptor->mRefCount > 0) | 
 | 4189 |                 && (!ignoreVirtualInputs || !isVirtualInputDevice(input_descriptor->mDevice))) { | 
 | 4190 |             return mInputs.keyAt(i); | 
 | 4191 |         } | 
 | 4192 |     } | 
 | 4193 |     return 0; | 
 | 4194 | } | 
 | 4195 |  | 
 | 4196 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4197 | audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4198 | { | 
 | 4199 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 4200 |         // this happens when forcing a route update and no track is active on an output. | 
 | 4201 |         // In this case the returned category is not important. | 
 | 4202 |         device =  AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4203 |     } else if (popcount(device) > 1) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4204 |         // Multiple device selection is either: | 
 | 4205 |         //  - speaker + one other device: give priority to speaker in this case. | 
 | 4206 |         //  - one A2DP device + another device: happens with duplicated output. In this case | 
 | 4207 |         // retain the device on the A2DP output as the other must not correspond to an active | 
 | 4208 |         // selection if not the speaker. | 
 | 4209 |         if (device & AUDIO_DEVICE_OUT_SPEAKER) { | 
 | 4210 |             device = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 4211 |         } else { | 
 | 4212 |             device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP); | 
 | 4213 |         } | 
 | 4214 |     } | 
 | 4215 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4216 |     ALOGW_IF(popcount(device) != 1, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4217 |             "getDeviceForVolume() invalid device combination: %08x", | 
 | 4218 |             device); | 
 | 4219 |  | 
 | 4220 |     return device; | 
 | 4221 | } | 
 | 4222 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4223 | AudioPolicyManager::device_category AudioPolicyManager::getDeviceCategory(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4224 | { | 
 | 4225 |     switch(getDeviceForVolume(device)) { | 
 | 4226 |         case AUDIO_DEVICE_OUT_EARPIECE: | 
 | 4227 |             return DEVICE_CATEGORY_EARPIECE; | 
 | 4228 |         case AUDIO_DEVICE_OUT_WIRED_HEADSET: | 
 | 4229 |         case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: | 
 | 4230 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO: | 
 | 4231 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: | 
 | 4232 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: | 
 | 4233 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: | 
 | 4234 |             return DEVICE_CATEGORY_HEADSET; | 
 | 4235 |         case AUDIO_DEVICE_OUT_SPEAKER: | 
 | 4236 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: | 
 | 4237 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: | 
 | 4238 |         case AUDIO_DEVICE_OUT_AUX_DIGITAL: | 
 | 4239 |         case AUDIO_DEVICE_OUT_USB_ACCESSORY: | 
 | 4240 |         case AUDIO_DEVICE_OUT_USB_DEVICE: | 
 | 4241 |         case AUDIO_DEVICE_OUT_REMOTE_SUBMIX: | 
 | 4242 |         default: | 
 | 4243 |             return DEVICE_CATEGORY_SPEAKER; | 
 | 4244 |     } | 
 | 4245 | } | 
 | 4246 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4247 | float AudioPolicyManager::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4248 |         int indexInUi) | 
 | 4249 | { | 
 | 4250 |     device_category deviceCategory = getDeviceCategory(device); | 
 | 4251 |     const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory]; | 
 | 4252 |  | 
 | 4253 |     // the volume index in the UI is relative to the min and max volume indices for this stream type | 
 | 4254 |     int nbSteps = 1 + curve[VOLMAX].mIndex - | 
 | 4255 |             curve[VOLMIN].mIndex; | 
 | 4256 |     int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) / | 
 | 4257 |             (streamDesc.mIndexMax - streamDesc.mIndexMin); | 
 | 4258 |  | 
 | 4259 |     // find what part of the curve this index volume belongs to, or if it's out of bounds | 
 | 4260 |     int segment = 0; | 
 | 4261 |     if (volIdx < curve[VOLMIN].mIndex) {         // out of bounds | 
 | 4262 |         return 0.0f; | 
 | 4263 |     } else if (volIdx < curve[VOLKNEE1].mIndex) { | 
 | 4264 |         segment = 0; | 
 | 4265 |     } else if (volIdx < curve[VOLKNEE2].mIndex) { | 
 | 4266 |         segment = 1; | 
 | 4267 |     } else if (volIdx <= curve[VOLMAX].mIndex) { | 
 | 4268 |         segment = 2; | 
 | 4269 |     } else {                                                               // out of bounds | 
 | 4270 |         return 1.0f; | 
 | 4271 |     } | 
 | 4272 |  | 
 | 4273 |     // linear interpolation in the attenuation table in dB | 
 | 4274 |     float decibels = curve[segment].mDBAttenuation + | 
 | 4275 |             ((float)(volIdx - curve[segment].mIndex)) * | 
 | 4276 |                 ( (curve[segment+1].mDBAttenuation - | 
 | 4277 |                         curve[segment].mDBAttenuation) / | 
 | 4278 |                     ((float)(curve[segment+1].mIndex - | 
 | 4279 |                             curve[segment].mIndex)) ); | 
 | 4280 |  | 
 | 4281 |     float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) | 
 | 4282 |  | 
 | 4283 |     ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", | 
 | 4284 |             curve[segment].mIndex, volIdx, | 
 | 4285 |             curve[segment+1].mIndex, | 
 | 4286 |             curve[segment].mDBAttenuation, | 
 | 4287 |             decibels, | 
 | 4288 |             curve[segment+1].mDBAttenuation, | 
 | 4289 |             amplification); | 
 | 4290 |  | 
 | 4291 |     return amplification; | 
 | 4292 | } | 
 | 4293 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4294 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4295 |     AudioPolicyManager::sDefaultVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4296 |     {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f} | 
 | 4297 | }; | 
 | 4298 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4299 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4300 |     AudioPolicyManager::sDefaultMediaVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4301 |     {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f} | 
 | 4302 | }; | 
 | 4303 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4304 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4305 |     AudioPolicyManager::sSpeakerMediaVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4306 |     {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f} | 
 | 4307 | }; | 
 | 4308 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4309 | const AudioPolicyManager::VolumeCurvePoint | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 4310 |     AudioPolicyManager::sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Jean-Michel Trivi | 98c6043 | 2014-07-09 08:51:34 -0700 | [diff] [blame] | 4311 |     {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] | 4312 | }; | 
 | 4313 |  | 
 | 4314 | const AudioPolicyManager::VolumeCurvePoint | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4315 |     AudioPolicyManager::sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4316 |     {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f} | 
 | 4317 | }; | 
 | 4318 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4319 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4320 |     AudioPolicyManager::sSpeakerSonificationVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4321 |     {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f} | 
 | 4322 | }; | 
 | 4323 |  | 
 | 4324 | // AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks | 
 | 4325 | // AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets. | 
 | 4326 | // AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java). | 
 | 4327 | // The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset. | 
 | 4328 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4329 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4330 |     AudioPolicyManager::sDefaultSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4331 |     {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f} | 
 | 4332 | }; | 
 | 4333 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4334 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4335 |     AudioPolicyManager::sDefaultSystemVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4336 |     {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f} | 
 | 4337 | }; | 
 | 4338 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4339 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4340 |     AudioPolicyManager::sHeadsetSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4341 |     {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f} | 
 | 4342 | }; | 
 | 4343 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4344 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4345 |     AudioPolicyManager::sDefaultVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4346 |     {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f} | 
 | 4347 | }; | 
 | 4348 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4349 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4350 |     AudioPolicyManager::sSpeakerVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4351 |     {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f} | 
 | 4352 | }; | 
 | 4353 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4354 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4355 |             *AudioPolicyManager::sVolumeProfiles[AUDIO_STREAM_CNT] | 
 | 4356 |                                                    [AudioPolicyManager::DEVICE_CATEGORY_CNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4357 |     { // AUDIO_STREAM_VOICE_CALL | 
 | 4358 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4359 |         sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4360 |         sDefaultVoiceVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4361 |     }, | 
 | 4362 |     { // AUDIO_STREAM_SYSTEM | 
 | 4363 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4364 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4365 |         sDefaultSystemVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4366 |     }, | 
 | 4367 |     { // AUDIO_STREAM_RING | 
 | 4368 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4369 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4370 |         sDefaultVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4371 |     }, | 
 | 4372 |     { // AUDIO_STREAM_MUSIC | 
 | 4373 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4374 |         sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4375 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4376 |     }, | 
 | 4377 |     { // AUDIO_STREAM_ALARM | 
 | 4378 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4379 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4380 |         sDefaultVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4381 |     }, | 
 | 4382 |     { // AUDIO_STREAM_NOTIFICATION | 
 | 4383 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4384 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4385 |         sDefaultVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4386 |     }, | 
 | 4387 |     { // AUDIO_STREAM_BLUETOOTH_SCO | 
 | 4388 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4389 |         sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4390 |         sDefaultVoiceVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4391 |     }, | 
 | 4392 |     { // AUDIO_STREAM_ENFORCED_AUDIBLE | 
 | 4393 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4394 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4395 |         sDefaultSystemVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4396 |     }, | 
 | 4397 |     {  // AUDIO_STREAM_DTMF | 
 | 4398 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4399 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4400 |         sDefaultSystemVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4401 |     }, | 
 | 4402 |     { // AUDIO_STREAM_TTS | 
 | 4403 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4404 |         sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4405 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4406 |     }, | 
 | 4407 | }; | 
 | 4408 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4409 | void AudioPolicyManager::initializeVolumeCurves() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4410 | { | 
 | 4411 |     for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
 | 4412 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 4413 |             mStreams[i].mVolumeCurve[j] = | 
 | 4414 |                     sVolumeProfiles[i][j]; | 
 | 4415 |         } | 
 | 4416 |     } | 
 | 4417 |  | 
 | 4418 |     // Check availability of DRC on speaker path: if available, override some of the speaker curves | 
 | 4419 |     if (mSpeakerDrcEnabled) { | 
 | 4420 |         mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4421 |                 sDefaultSystemVolumeCurveDrc; | 
 | 4422 |         mStreams[AUDIO_STREAM_RING].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4423 |                 sSpeakerSonificationVolumeCurveDrc; | 
 | 4424 |         mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4425 |                 sSpeakerSonificationVolumeCurveDrc; | 
 | 4426 |         mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4427 |                 sSpeakerSonificationVolumeCurveDrc; | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 4428 |         mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4429 |                 sSpeakerMediaVolumeCurveDrc; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4430 |     } | 
 | 4431 | } | 
 | 4432 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4433 | float AudioPolicyManager::computeVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4434 |                                             int index, | 
 | 4435 |                                             audio_io_handle_t output, | 
 | 4436 |                                             audio_devices_t device) | 
 | 4437 | { | 
 | 4438 |     float volume = 1.0; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4439 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4440 |     StreamDescriptor &streamDesc = mStreams[stream]; | 
 | 4441 |  | 
 | 4442 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 4443 |         device = outputDesc->device(); | 
 | 4444 |     } | 
 | 4445 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4446 |     volume = volIndexToAmpl(device, streamDesc, index); | 
 | 4447 |  | 
 | 4448 |     // if a headset is connected, apply the following rules to ring tones and notifications | 
 | 4449 |     // to avoid sound level bursts in user's ears: | 
 | 4450 |     // - always attenuate ring tones and notifications volume by 6dB | 
 | 4451 |     // - if music is playing, always limit the volume to current music volume, | 
 | 4452 |     // with a minimum threshold at -36dB so that notification is always perceived. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4453 |     const routing_strategy stream_strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4454 |     if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | | 
 | 4455 |             AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | | 
 | 4456 |             AUDIO_DEVICE_OUT_WIRED_HEADSET | | 
 | 4457 |             AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) && | 
 | 4458 |         ((stream_strategy == STRATEGY_SONIFICATION) | 
 | 4459 |                 || (stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL) | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4460 |                 || (stream == AUDIO_STREAM_SYSTEM) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4461 |                 || ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4462 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4463 |         streamDesc.mCanBeMuted) { | 
 | 4464 |         volume *= SONIFICATION_HEADSET_VOLUME_FACTOR; | 
 | 4465 |         // when the phone is ringing we must consider that music could have been paused just before | 
 | 4466 |         // by the music application and behave as if music was active if the last music track was | 
 | 4467 |         // just stopped | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4468 |         if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4469 |                 mLimitRingtoneVolume) { | 
 | 4470 |             audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4471 |             float musicVol = computeVolume(AUDIO_STREAM_MUSIC, | 
 | 4472 |                                mStreams[AUDIO_STREAM_MUSIC].getVolumeIndex(musicDevice), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4473 |                                output, | 
 | 4474 |                                musicDevice); | 
 | 4475 |             float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? | 
 | 4476 |                                 musicVol : SONIFICATION_HEADSET_VOLUME_MIN; | 
 | 4477 |             if (volume > minVol) { | 
 | 4478 |                 volume = minVol; | 
 | 4479 |                 ALOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol); | 
 | 4480 |             } | 
 | 4481 |         } | 
 | 4482 |     } | 
 | 4483 |  | 
 | 4484 |     return volume; | 
 | 4485 | } | 
 | 4486 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4487 | status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4488 |                                                    int index, | 
 | 4489 |                                                    audio_io_handle_t output, | 
 | 4490 |                                                    audio_devices_t device, | 
 | 4491 |                                                    int delayMs, | 
 | 4492 |                                                    bool force) | 
 | 4493 | { | 
 | 4494 |  | 
 | 4495 |     // do not change actual stream volume if the stream is muted | 
 | 4496 |     if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { | 
 | 4497 |         ALOGVV("checkAndSetVolume() stream %d muted count %d", | 
 | 4498 |               stream, mOutputs.valueFor(output)->mMuteCount[stream]); | 
 | 4499 |         return NO_ERROR; | 
 | 4500 |     } | 
 | 4501 |  | 
 | 4502 |     // 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] | 4503 |     if ((stream == AUDIO_STREAM_VOICE_CALL && | 
 | 4504 |             mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) || | 
 | 4505 |         (stream == AUDIO_STREAM_BLUETOOTH_SCO && | 
 | 4506 |                 mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4507 |         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] | 4508 |              stream, mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4509 |         return INVALID_OPERATION; | 
 | 4510 |     } | 
 | 4511 |  | 
 | 4512 |     float volume = computeVolume(stream, index, output, device); | 
 | 4513 |     // We actually change the volume if: | 
 | 4514 |     // - the float value returned by computeVolume() changed | 
 | 4515 |     // - the force flag is set | 
 | 4516 |     if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || | 
 | 4517 |             force) { | 
 | 4518 |         mOutputs.valueFor(output)->mCurVolume[stream] = volume; | 
 | 4519 |         ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); | 
 | 4520 |         // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is | 
 | 4521 |         // enabled | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4522 |         if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { | 
 | 4523 |             mpClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume, output, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4524 |         } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4525 |         mpClientInterface->setStreamVolume(stream, volume, output, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4526 |     } | 
 | 4527 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4528 |     if (stream == AUDIO_STREAM_VOICE_CALL || | 
 | 4529 |         stream == AUDIO_STREAM_BLUETOOTH_SCO) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4530 |         float voiceVolume; | 
 | 4531 |         // 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] | 4532 |         if (stream == AUDIO_STREAM_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4533 |             voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; | 
 | 4534 |         } else { | 
 | 4535 |             voiceVolume = 1.0; | 
 | 4536 |         } | 
 | 4537 |  | 
 | 4538 |         if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) { | 
 | 4539 |             mpClientInterface->setVoiceVolume(voiceVolume, delayMs); | 
 | 4540 |             mLastVoiceVolume = voiceVolume; | 
 | 4541 |         } | 
 | 4542 |     } | 
 | 4543 |  | 
 | 4544 |     return NO_ERROR; | 
 | 4545 | } | 
 | 4546 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4547 | void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4548 |                                                 audio_devices_t device, | 
 | 4549 |                                                 int delayMs, | 
 | 4550 |                                                 bool force) | 
 | 4551 | { | 
 | 4552 |     ALOGVV("applyStreamVolumes() for output %d and device %x", output, device); | 
 | 4553 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4554 |     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 4555 |         checkAndSetVolume((audio_stream_type_t)stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4556 |                           mStreams[stream].getVolumeIndex(device), | 
 | 4557 |                           output, | 
 | 4558 |                           device, | 
 | 4559 |                           delayMs, | 
 | 4560 |                           force); | 
 | 4561 |     } | 
 | 4562 | } | 
 | 4563 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4564 | void AudioPolicyManager::setStrategyMute(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4565 |                                              bool on, | 
 | 4566 |                                              audio_io_handle_t output, | 
 | 4567 |                                              int delayMs, | 
 | 4568 |                                              audio_devices_t device) | 
 | 4569 | { | 
 | 4570 |     ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4571 |     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 4572 |         if (getStrategy((audio_stream_type_t)stream) == strategy) { | 
 | 4573 |             setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4574 |         } | 
 | 4575 |     } | 
 | 4576 | } | 
 | 4577 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4578 | void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4579 |                                            bool on, | 
 | 4580 |                                            audio_io_handle_t output, | 
 | 4581 |                                            int delayMs, | 
 | 4582 |                                            audio_devices_t device) | 
 | 4583 | { | 
 | 4584 |     StreamDescriptor &streamDesc = mStreams[stream]; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4585 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4586 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 4587 |         device = outputDesc->device(); | 
 | 4588 |     } | 
 | 4589 |  | 
 | 4590 |     ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x", | 
 | 4591 |           stream, on, output, outputDesc->mMuteCount[stream], device); | 
 | 4592 |  | 
 | 4593 |     if (on) { | 
 | 4594 |         if (outputDesc->mMuteCount[stream] == 0) { | 
 | 4595 |             if (streamDesc.mCanBeMuted && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4596 |                     ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) || | 
 | 4597 |                      (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4598 |                 checkAndSetVolume(stream, 0, output, device, delayMs); | 
 | 4599 |             } | 
 | 4600 |         } | 
 | 4601 |         // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored | 
 | 4602 |         outputDesc->mMuteCount[stream]++; | 
 | 4603 |     } else { | 
 | 4604 |         if (outputDesc->mMuteCount[stream] == 0) { | 
 | 4605 |             ALOGV("setStreamMute() unmuting non muted stream!"); | 
 | 4606 |             return; | 
 | 4607 |         } | 
 | 4608 |         if (--outputDesc->mMuteCount[stream] == 0) { | 
 | 4609 |             checkAndSetVolume(stream, | 
 | 4610 |                               streamDesc.getVolumeIndex(device), | 
 | 4611 |                               output, | 
 | 4612 |                               device, | 
 | 4613 |                               delayMs); | 
 | 4614 |         } | 
 | 4615 |     } | 
 | 4616 | } | 
 | 4617 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4618 | void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4619 |                                                       bool starting, bool stateChange) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4620 | { | 
 | 4621 |     // if the stream pertains to sonification strategy and we are in call we must | 
 | 4622 |     // mute the stream if it is low visibility. If it is high visibility, we must play a tone | 
 | 4623 |     // in the device used for phone strategy and play the tone if the selected device does not | 
 | 4624 |     // interfere with the device used for phone strategy | 
 | 4625 |     // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as | 
 | 4626 |     // many times as there are active tracks on the output | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4627 |     const routing_strategy stream_strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4628 |     if ((stream_strategy == STRATEGY_SONIFICATION) || | 
 | 4629 |             ((stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL))) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4630 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4631 |         ALOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d", | 
 | 4632 |                 stream, starting, outputDesc->mDevice, stateChange); | 
 | 4633 |         if (outputDesc->mRefCount[stream]) { | 
 | 4634 |             int muteCount = 1; | 
 | 4635 |             if (stateChange) { | 
 | 4636 |                 muteCount = outputDesc->mRefCount[stream]; | 
 | 4637 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4638 |             if (audio_is_low_visibility(stream)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4639 |                 ALOGV("handleIncallSonification() low visibility, muteCount %d", muteCount); | 
 | 4640 |                 for (int i = 0; i < muteCount; i++) { | 
 | 4641 |                     setStreamMute(stream, starting, mPrimaryOutput); | 
 | 4642 |                 } | 
 | 4643 |             } else { | 
 | 4644 |                 ALOGV("handleIncallSonification() high visibility"); | 
 | 4645 |                 if (outputDesc->device() & | 
 | 4646 |                         getDeviceForStrategy(STRATEGY_PHONE, true /*fromCache*/)) { | 
 | 4647 |                     ALOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount); | 
 | 4648 |                     for (int i = 0; i < muteCount; i++) { | 
 | 4649 |                         setStreamMute(stream, starting, mPrimaryOutput); | 
 | 4650 |                     } | 
 | 4651 |                 } | 
 | 4652 |                 if (starting) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4653 |                     mpClientInterface->startTone(AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION, | 
 | 4654 |                                                  AUDIO_STREAM_VOICE_CALL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4655 |                 } else { | 
 | 4656 |                     mpClientInterface->stopTone(); | 
 | 4657 |                 } | 
 | 4658 |             } | 
 | 4659 |         } | 
 | 4660 |     } | 
 | 4661 | } | 
 | 4662 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4663 | bool AudioPolicyManager::isInCall() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4664 | { | 
 | 4665 |     return isStateInCall(mPhoneState); | 
 | 4666 | } | 
 | 4667 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4668 | bool AudioPolicyManager::isStateInCall(int state) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4669 |     return ((state == AUDIO_MODE_IN_CALL) || | 
 | 4670 |             (state == AUDIO_MODE_IN_COMMUNICATION)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4671 | } | 
 | 4672 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4673 | uint32_t AudioPolicyManager::getMaxEffectsCpuLoad() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4674 | { | 
 | 4675 |     return MAX_EFFECTS_CPU_LOAD; | 
 | 4676 | } | 
 | 4677 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4678 | uint32_t AudioPolicyManager::getMaxEffectsMemory() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4679 | { | 
 | 4680 |     return MAX_EFFECTS_MEMORY; | 
 | 4681 | } | 
 | 4682 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4683 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4684 | // --- AudioOutputDescriptor class implementation | 
 | 4685 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4686 | AudioPolicyManager::AudioOutputDescriptor::AudioOutputDescriptor( | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4687 |         const sp<IOProfile>& profile) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4688 |     : mId(0), mIoHandle(0), mLatency(0), | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4689 |     mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4690 |     mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0) | 
 | 4691 | { | 
 | 4692 |     // clear usage count for all stream types | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4693 |     for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4694 |         mRefCount[i] = 0; | 
 | 4695 |         mCurVolume[i] = -1.0; | 
 | 4696 |         mMuteCount[i] = 0; | 
 | 4697 |         mStopTime[i] = 0; | 
 | 4698 |     } | 
 | 4699 |     for (int i = 0; i < NUM_STRATEGIES; i++) { | 
 | 4700 |         mStrategyMutedByDevice[i] = false; | 
 | 4701 |     } | 
 | 4702 |     if (profile != NULL) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4703 |         mAudioPort = profile; | 
| Eric Laurent | d862237 | 2014-07-27 13:47:31 -0700 | [diff] [blame] | 4704 |         mFlags = profile->mFlags; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 4705 |         mSamplingRate = profile->pickSamplingRate(); | 
 | 4706 |         mFormat = profile->pickFormat(); | 
 | 4707 |         mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 4708 |         if (profile->mGains.size() > 0) { | 
 | 4709 |             profile->mGains[0]->getDefaultConfig(&mGain); | 
 | 4710 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4711 |     } | 
 | 4712 | } | 
 | 4713 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4714 | audio_devices_t AudioPolicyManager::AudioOutputDescriptor::device() const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4715 | { | 
 | 4716 |     if (isDuplicated()) { | 
 | 4717 |         return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); | 
 | 4718 |     } else { | 
 | 4719 |         return mDevice; | 
 | 4720 |     } | 
 | 4721 | } | 
 | 4722 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4723 | uint32_t AudioPolicyManager::AudioOutputDescriptor::latency() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4724 | { | 
 | 4725 |     if (isDuplicated()) { | 
 | 4726 |         return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; | 
 | 4727 |     } else { | 
 | 4728 |         return mLatency; | 
 | 4729 |     } | 
 | 4730 | } | 
 | 4731 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4732 | bool AudioPolicyManager::AudioOutputDescriptor::sharesHwModuleWith( | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4733 |         const sp<AudioOutputDescriptor> outputDesc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4734 | { | 
 | 4735 |     if (isDuplicated()) { | 
 | 4736 |         return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); | 
 | 4737 |     } else if (outputDesc->isDuplicated()){ | 
 | 4738 |         return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); | 
 | 4739 |     } else { | 
 | 4740 |         return (mProfile->mModule == outputDesc->mProfile->mModule); | 
 | 4741 |     } | 
 | 4742 | } | 
 | 4743 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4744 | void AudioPolicyManager::AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4745 |                                                                    int delta) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4746 | { | 
 | 4747 |     // forward usage count change to attached outputs | 
 | 4748 |     if (isDuplicated()) { | 
 | 4749 |         mOutput1->changeRefCount(stream, delta); | 
 | 4750 |         mOutput2->changeRefCount(stream, delta); | 
 | 4751 |     } | 
 | 4752 |     if ((delta + (int)mRefCount[stream]) < 0) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4753 |         ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", | 
 | 4754 |               delta, stream, mRefCount[stream]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4755 |         mRefCount[stream] = 0; | 
 | 4756 |         return; | 
 | 4757 |     } | 
 | 4758 |     mRefCount[stream] += delta; | 
 | 4759 |     ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); | 
 | 4760 | } | 
 | 4761 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4762 | audio_devices_t AudioPolicyManager::AudioOutputDescriptor::supportedDevices() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4763 | { | 
 | 4764 |     if (isDuplicated()) { | 
 | 4765 |         return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); | 
 | 4766 |     } else { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4767 |         return mProfile->mSupportedDevices.types() ; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4768 |     } | 
 | 4769 | } | 
 | 4770 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4771 | bool AudioPolicyManager::AudioOutputDescriptor::isActive(uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4772 | { | 
 | 4773 |     return isStrategyActive(NUM_STRATEGIES, inPastMs); | 
 | 4774 | } | 
 | 4775 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4776 | bool AudioPolicyManager::AudioOutputDescriptor::isStrategyActive(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4777 |                                                                        uint32_t inPastMs, | 
 | 4778 |                                                                        nsecs_t sysTime) const | 
 | 4779 | { | 
 | 4780 |     if ((sysTime == 0) && (inPastMs != 0)) { | 
 | 4781 |         sysTime = systemTime(); | 
 | 4782 |     } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4783 |     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { | 
 | 4784 |         if (((getStrategy((audio_stream_type_t)i) == strategy) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4785 |                 (NUM_STRATEGIES == strategy)) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4786 |                 isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4787 |             return true; | 
 | 4788 |         } | 
 | 4789 |     } | 
 | 4790 |     return false; | 
 | 4791 | } | 
 | 4792 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4793 | bool AudioPolicyManager::AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4794 |                                                                        uint32_t inPastMs, | 
 | 4795 |                                                                        nsecs_t sysTime) const | 
 | 4796 | { | 
 | 4797 |     if (mRefCount[stream] != 0) { | 
 | 4798 |         return true; | 
 | 4799 |     } | 
 | 4800 |     if (inPastMs == 0) { | 
 | 4801 |         return false; | 
 | 4802 |     } | 
 | 4803 |     if (sysTime == 0) { | 
 | 4804 |         sysTime = systemTime(); | 
 | 4805 |     } | 
 | 4806 |     if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { | 
 | 4807 |         return true; | 
 | 4808 |     } | 
 | 4809 |     return false; | 
 | 4810 | } | 
 | 4811 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4812 | void AudioPolicyManager::AudioOutputDescriptor::toAudioPortConfig( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4813 |                                                  struct audio_port_config *dstConfig, | 
 | 4814 |                                                  const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4815 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4816 |     ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); | 
 | 4817 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4818 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| | 
 | 4819 |                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; | 
 | 4820 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4821 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4822 |     } | 
 | 4823 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 4824 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4825 |     dstConfig->id = mId; | 
 | 4826 |     dstConfig->role = AUDIO_PORT_ROLE_SOURCE; | 
 | 4827 |     dstConfig->type = AUDIO_PORT_TYPE_MIX; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4828 |     dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; | 
 | 4829 |     dstConfig->ext.mix.handle = mIoHandle; | 
 | 4830 |     dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4831 | } | 
 | 4832 |  | 
 | 4833 | void AudioPolicyManager::AudioOutputDescriptor::toAudioPort( | 
 | 4834 |                                                     struct audio_port *port) const | 
 | 4835 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4836 |     ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4837 |     mProfile->toAudioPort(port); | 
 | 4838 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4839 |     toAudioPortConfig(&port->active_config); | 
 | 4840 |     port->ext.mix.hw_module = mProfile->mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4841 |     port->ext.mix.handle = mIoHandle; | 
 | 4842 |     port->ext.mix.latency_class = | 
 | 4843 |             mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; | 
 | 4844 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4845 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4846 | status_t AudioPolicyManager::AudioOutputDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4847 | { | 
 | 4848 |     const size_t SIZE = 256; | 
 | 4849 |     char buffer[SIZE]; | 
 | 4850 |     String8 result; | 
 | 4851 |  | 
 | 4852 |     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); | 
 | 4853 |     result.append(buffer); | 
 | 4854 |     snprintf(buffer, SIZE, " Format: %08x\n", mFormat); | 
 | 4855 |     result.append(buffer); | 
 | 4856 |     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); | 
 | 4857 |     result.append(buffer); | 
 | 4858 |     snprintf(buffer, SIZE, " Latency: %d\n", mLatency); | 
 | 4859 |     result.append(buffer); | 
 | 4860 |     snprintf(buffer, SIZE, " Flags %08x\n", mFlags); | 
 | 4861 |     result.append(buffer); | 
 | 4862 |     snprintf(buffer, SIZE, " Devices %08x\n", device()); | 
 | 4863 |     result.append(buffer); | 
 | 4864 |     snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); | 
 | 4865 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4866 |     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { | 
 | 4867 |         snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n", | 
 | 4868 |                  i, mCurVolume[i], mRefCount[i], mMuteCount[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4869 |         result.append(buffer); | 
 | 4870 |     } | 
 | 4871 |     write(fd, result.string(), result.size()); | 
 | 4872 |  | 
 | 4873 |     return NO_ERROR; | 
 | 4874 | } | 
 | 4875 |  | 
 | 4876 | // --- AudioInputDescriptor class implementation | 
 | 4877 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4878 | AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4879 |     : mId(0), mIoHandle(0), | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4880 |       mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), mRefCount(0), | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4881 |       mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4882 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4883 |     if (profile != NULL) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4884 |         mAudioPort = profile; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 4885 |         mSamplingRate = profile->pickSamplingRate(); | 
 | 4886 |         mFormat = profile->pickFormat(); | 
 | 4887 |         mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 4888 |         if (profile->mGains.size() > 0) { | 
 | 4889 |             profile->mGains[0]->getDefaultConfig(&mGain); | 
 | 4890 |         } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4891 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4892 | } | 
 | 4893 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4894 | void AudioPolicyManager::AudioInputDescriptor::toAudioPortConfig( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4895 |                                                    struct audio_port_config *dstConfig, | 
 | 4896 |                                                    const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4897 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4898 |     ALOG_ASSERT(mProfile != 0, | 
 | 4899 |                 "toAudioPortConfig() called on input with null profile %d", mIoHandle); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4900 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| | 
 | 4901 |                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; | 
 | 4902 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4903 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4904 |     } | 
 | 4905 |  | 
 | 4906 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 4907 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4908 |     dstConfig->id = mId; | 
 | 4909 |     dstConfig->role = AUDIO_PORT_ROLE_SINK; | 
 | 4910 |     dstConfig->type = AUDIO_PORT_TYPE_MIX; | 
| Eric Laurent | 62aaabb | 2014-06-02 10:40:54 -0700 | [diff] [blame] | 4911 |     dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; | 
 | 4912 |     dstConfig->ext.mix.handle = mIoHandle; | 
 | 4913 |     dstConfig->ext.mix.usecase.source = mInputSource; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4914 | } | 
 | 4915 |  | 
 | 4916 | void AudioPolicyManager::AudioInputDescriptor::toAudioPort( | 
 | 4917 |                                                     struct audio_port *port) const | 
 | 4918 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4919 |     ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle); | 
 | 4920 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4921 |     mProfile->toAudioPort(port); | 
 | 4922 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4923 |     toAudioPortConfig(&port->active_config); | 
 | 4924 |     port->ext.mix.hw_module = mProfile->mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4925 |     port->ext.mix.handle = mIoHandle; | 
 | 4926 |     port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL; | 
 | 4927 | } | 
 | 4928 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4929 | status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4930 | { | 
 | 4931 |     const size_t SIZE = 256; | 
 | 4932 |     char buffer[SIZE]; | 
 | 4933 |     String8 result; | 
 | 4934 |  | 
 | 4935 |     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); | 
 | 4936 |     result.append(buffer); | 
 | 4937 |     snprintf(buffer, SIZE, " Format: %d\n", mFormat); | 
 | 4938 |     result.append(buffer); | 
 | 4939 |     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); | 
 | 4940 |     result.append(buffer); | 
 | 4941 |     snprintf(buffer, SIZE, " Devices %08x\n", mDevice); | 
 | 4942 |     result.append(buffer); | 
 | 4943 |     snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount); | 
 | 4944 |     result.append(buffer); | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame] | 4945 |     snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount); | 
 | 4946 |     result.append(buffer); | 
 | 4947 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4948 |     write(fd, result.string(), result.size()); | 
 | 4949 |  | 
 | 4950 |     return NO_ERROR; | 
 | 4951 | } | 
 | 4952 |  | 
 | 4953 | // --- StreamDescriptor class implementation | 
 | 4954 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4955 | AudioPolicyManager::StreamDescriptor::StreamDescriptor() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4956 |     :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true) | 
 | 4957 | { | 
 | 4958 |     mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0); | 
 | 4959 | } | 
 | 4960 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4961 | int AudioPolicyManager::StreamDescriptor::getVolumeIndex(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4962 | { | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4963 |     device = AudioPolicyManager::getDeviceForVolume(device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4964 |     // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT | 
 | 4965 |     if (mIndexCur.indexOfKey(device) < 0) { | 
 | 4966 |         device = AUDIO_DEVICE_OUT_DEFAULT; | 
 | 4967 |     } | 
 | 4968 |     return mIndexCur.valueFor(device); | 
 | 4969 | } | 
 | 4970 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4971 | void AudioPolicyManager::StreamDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4972 | { | 
 | 4973 |     const size_t SIZE = 256; | 
 | 4974 |     char buffer[SIZE]; | 
 | 4975 |     String8 result; | 
 | 4976 |  | 
 | 4977 |     snprintf(buffer, SIZE, "%s         %02d         %02d         ", | 
 | 4978 |              mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax); | 
 | 4979 |     result.append(buffer); | 
 | 4980 |     for (size_t i = 0; i < mIndexCur.size(); i++) { | 
 | 4981 |         snprintf(buffer, SIZE, "%04x : %02d, ", | 
 | 4982 |                  mIndexCur.keyAt(i), | 
 | 4983 |                  mIndexCur.valueAt(i)); | 
 | 4984 |         result.append(buffer); | 
 | 4985 |     } | 
 | 4986 |     result.append("\n"); | 
 | 4987 |  | 
 | 4988 |     write(fd, result.string(), result.size()); | 
 | 4989 | } | 
 | 4990 |  | 
 | 4991 | // --- EffectDescriptor class implementation | 
 | 4992 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4993 | status_t AudioPolicyManager::EffectDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4994 | { | 
 | 4995 |     const size_t SIZE = 256; | 
 | 4996 |     char buffer[SIZE]; | 
 | 4997 |     String8 result; | 
 | 4998 |  | 
 | 4999 |     snprintf(buffer, SIZE, " I/O: %d\n", mIo); | 
 | 5000 |     result.append(buffer); | 
 | 5001 |     snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy); | 
 | 5002 |     result.append(buffer); | 
 | 5003 |     snprintf(buffer, SIZE, " Session: %d\n", mSession); | 
 | 5004 |     result.append(buffer); | 
 | 5005 |     snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name); | 
 | 5006 |     result.append(buffer); | 
 | 5007 |     snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled"); | 
 | 5008 |     result.append(buffer); | 
 | 5009 |     write(fd, result.string(), result.size()); | 
 | 5010 |  | 
 | 5011 |     return NO_ERROR; | 
 | 5012 | } | 
 | 5013 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5014 | // --- HwModule class implementation | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5015 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5016 | AudioPolicyManager::HwModule::HwModule(const char *name) | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 5017 |     : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)), | 
 | 5018 |       mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5019 | { | 
 | 5020 | } | 
 | 5021 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5022 | AudioPolicyManager::HwModule::~HwModule() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5023 | { | 
 | 5024 |     for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5025 |         mOutputProfiles[i]->mSupportedDevices.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5026 |     } | 
 | 5027 |     for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5028 |         mInputProfiles[i]->mSupportedDevices.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5029 |     } | 
 | 5030 |     free((void *)mName); | 
 | 5031 | } | 
 | 5032 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5033 | status_t AudioPolicyManager::HwModule::loadInput(cnode *root) | 
 | 5034 | { | 
 | 5035 |     cnode *node = root->first_child; | 
 | 5036 |  | 
 | 5037 |     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this); | 
 | 5038 |  | 
 | 5039 |     while (node) { | 
 | 5040 |         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { | 
 | 5041 |             profile->loadSamplingRates((char *)node->value); | 
 | 5042 |         } else if (strcmp(node->name, FORMATS_TAG) == 0) { | 
 | 5043 |             profile->loadFormats((char *)node->value); | 
 | 5044 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 5045 |             profile->loadInChannels((char *)node->value); | 
 | 5046 |         } else if (strcmp(node->name, DEVICES_TAG) == 0) { | 
 | 5047 |             profile->mSupportedDevices.loadDevicesFromName((char *)node->value, | 
 | 5048 |                                                            mDeclaredDevices); | 
 | 5049 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 5050 |             profile->loadGains(node); | 
 | 5051 |         } | 
 | 5052 |         node = node->next; | 
 | 5053 |     } | 
 | 5054 |     ALOGW_IF(profile->mSupportedDevices.isEmpty(), | 
 | 5055 |             "loadInput() invalid supported devices"); | 
 | 5056 |     ALOGW_IF(profile->mChannelMasks.size() == 0, | 
 | 5057 |             "loadInput() invalid supported channel masks"); | 
 | 5058 |     ALOGW_IF(profile->mSamplingRates.size() == 0, | 
 | 5059 |             "loadInput() invalid supported sampling rates"); | 
 | 5060 |     ALOGW_IF(profile->mFormats.size() == 0, | 
 | 5061 |             "loadInput() invalid supported formats"); | 
 | 5062 |     if (!profile->mSupportedDevices.isEmpty() && | 
 | 5063 |             (profile->mChannelMasks.size() != 0) && | 
 | 5064 |             (profile->mSamplingRates.size() != 0) && | 
 | 5065 |             (profile->mFormats.size() != 0)) { | 
 | 5066 |  | 
 | 5067 |         ALOGV("loadInput() adding input Supported Devices %04x", | 
 | 5068 |               profile->mSupportedDevices.types()); | 
 | 5069 |  | 
 | 5070 |         mInputProfiles.add(profile); | 
 | 5071 |         return NO_ERROR; | 
 | 5072 |     } else { | 
 | 5073 |         return BAD_VALUE; | 
 | 5074 |     } | 
 | 5075 | } | 
 | 5076 |  | 
 | 5077 | status_t AudioPolicyManager::HwModule::loadOutput(cnode *root) | 
 | 5078 | { | 
 | 5079 |     cnode *node = root->first_child; | 
 | 5080 |  | 
 | 5081 |     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this); | 
 | 5082 |  | 
 | 5083 |     while (node) { | 
 | 5084 |         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { | 
 | 5085 |             profile->loadSamplingRates((char *)node->value); | 
 | 5086 |         } else if (strcmp(node->name, FORMATS_TAG) == 0) { | 
 | 5087 |             profile->loadFormats((char *)node->value); | 
 | 5088 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 5089 |             profile->loadOutChannels((char *)node->value); | 
 | 5090 |         } else if (strcmp(node->name, DEVICES_TAG) == 0) { | 
 | 5091 |             profile->mSupportedDevices.loadDevicesFromName((char *)node->value, | 
 | 5092 |                                                            mDeclaredDevices); | 
 | 5093 |         } else if (strcmp(node->name, FLAGS_TAG) == 0) { | 
 | 5094 |             profile->mFlags = parseFlagNames((char *)node->value); | 
 | 5095 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 5096 |             profile->loadGains(node); | 
 | 5097 |         } | 
 | 5098 |         node = node->next; | 
 | 5099 |     } | 
 | 5100 |     ALOGW_IF(profile->mSupportedDevices.isEmpty(), | 
 | 5101 |             "loadOutput() invalid supported devices"); | 
 | 5102 |     ALOGW_IF(profile->mChannelMasks.size() == 0, | 
 | 5103 |             "loadOutput() invalid supported channel masks"); | 
 | 5104 |     ALOGW_IF(profile->mSamplingRates.size() == 0, | 
 | 5105 |             "loadOutput() invalid supported sampling rates"); | 
 | 5106 |     ALOGW_IF(profile->mFormats.size() == 0, | 
 | 5107 |             "loadOutput() invalid supported formats"); | 
 | 5108 |     if (!profile->mSupportedDevices.isEmpty() && | 
 | 5109 |             (profile->mChannelMasks.size() != 0) && | 
 | 5110 |             (profile->mSamplingRates.size() != 0) && | 
 | 5111 |             (profile->mFormats.size() != 0)) { | 
 | 5112 |  | 
 | 5113 |         ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x", | 
 | 5114 |               profile->mSupportedDevices.types(), profile->mFlags); | 
 | 5115 |  | 
 | 5116 |         mOutputProfiles.add(profile); | 
 | 5117 |         return NO_ERROR; | 
 | 5118 |     } else { | 
 | 5119 |         return BAD_VALUE; | 
 | 5120 |     } | 
 | 5121 | } | 
 | 5122 |  | 
 | 5123 | status_t AudioPolicyManager::HwModule::loadDevice(cnode *root) | 
 | 5124 | { | 
 | 5125 |     cnode *node = root->first_child; | 
 | 5126 |  | 
 | 5127 |     audio_devices_t type = AUDIO_DEVICE_NONE; | 
 | 5128 |     while (node) { | 
 | 5129 |         if (strcmp(node->name, DEVICE_TYPE) == 0) { | 
 | 5130 |             type = parseDeviceNames((char *)node->value); | 
 | 5131 |             break; | 
 | 5132 |         } | 
 | 5133 |         node = node->next; | 
 | 5134 |     } | 
 | 5135 |     if (type == AUDIO_DEVICE_NONE || | 
 | 5136 |             (!audio_is_input_device(type) && !audio_is_output_device(type))) { | 
 | 5137 |         ALOGW("loadDevice() bad type %08x", type); | 
 | 5138 |         return BAD_VALUE; | 
 | 5139 |     } | 
 | 5140 |     sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type); | 
 | 5141 |     deviceDesc->mModule = this; | 
 | 5142 |  | 
 | 5143 |     node = root->first_child; | 
 | 5144 |     while (node) { | 
 | 5145 |         if (strcmp(node->name, DEVICE_ADDRESS) == 0) { | 
 | 5146 |             deviceDesc->mAddress = String8((char *)node->value); | 
 | 5147 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 5148 |             if (audio_is_input_device(type)) { | 
 | 5149 |                 deviceDesc->loadInChannels((char *)node->value); | 
 | 5150 |             } else { | 
 | 5151 |                 deviceDesc->loadOutChannels((char *)node->value); | 
 | 5152 |             } | 
 | 5153 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 5154 |             deviceDesc->loadGains(node); | 
 | 5155 |         } | 
 | 5156 |         node = node->next; | 
 | 5157 |     } | 
 | 5158 |  | 
 | 5159 |     ALOGV("loadDevice() adding device name %s type %08x address %s", | 
 | 5160 |           deviceDesc->mName.string(), type, deviceDesc->mAddress.string()); | 
 | 5161 |  | 
 | 5162 |     mDeclaredDevices.add(deviceDesc); | 
 | 5163 |  | 
 | 5164 |     return NO_ERROR; | 
 | 5165 | } | 
 | 5166 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5167 | void AudioPolicyManager::HwModule::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5168 | { | 
 | 5169 |     const size_t SIZE = 256; | 
 | 5170 |     char buffer[SIZE]; | 
 | 5171 |     String8 result; | 
 | 5172 |  | 
 | 5173 |     snprintf(buffer, SIZE, "  - name: %s\n", mName); | 
 | 5174 |     result.append(buffer); | 
 | 5175 |     snprintf(buffer, SIZE, "  - handle: %d\n", mHandle); | 
 | 5176 |     result.append(buffer); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 5177 |     snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF); | 
 | 5178 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5179 |     write(fd, result.string(), result.size()); | 
 | 5180 |     if (mOutputProfiles.size()) { | 
 | 5181 |         write(fd, "  - outputs:\n", strlen("  - outputs:\n")); | 
 | 5182 |         for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5183 |             snprintf(buffer, SIZE, "    output %zu:\n", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5184 |             write(fd, buffer, strlen(buffer)); | 
 | 5185 |             mOutputProfiles[i]->dump(fd); | 
 | 5186 |         } | 
 | 5187 |     } | 
 | 5188 |     if (mInputProfiles.size()) { | 
 | 5189 |         write(fd, "  - inputs:\n", strlen("  - inputs:\n")); | 
 | 5190 |         for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5191 |             snprintf(buffer, SIZE, "    input %zu:\n", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5192 |             write(fd, buffer, strlen(buffer)); | 
 | 5193 |             mInputProfiles[i]->dump(fd); | 
 | 5194 |         } | 
 | 5195 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5196 |     if (mDeclaredDevices.size()) { | 
 | 5197 |         write(fd, "  - devices:\n", strlen("  - devices:\n")); | 
 | 5198 |         for (size_t i = 0; i < mDeclaredDevices.size(); i++) { | 
 | 5199 |             mDeclaredDevices[i]->dump(fd, 4, i); | 
 | 5200 |         } | 
 | 5201 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5202 | } | 
 | 5203 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5204 | // --- AudioPort class implementation | 
 | 5205 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5206 |  | 
 | 5207 | AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type, | 
 | 5208 |           audio_port_role_t role, const sp<HwModule>& module) : | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5209 |     mName(name), mType(type), mRole(role), mModule(module), mFlags((audio_output_flags_t)0) | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5210 | { | 
 | 5211 |     mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || | 
 | 5212 |                     ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); | 
 | 5213 | } | 
 | 5214 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5215 | void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const | 
 | 5216 | { | 
 | 5217 |     port->role = mRole; | 
 | 5218 |     port->type = mType; | 
 | 5219 |     unsigned int i; | 
 | 5220 |     for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) { | 
 | 5221 |         port->sample_rates[i] = mSamplingRates[i]; | 
 | 5222 |     } | 
 | 5223 |     port->num_sample_rates = i; | 
 | 5224 |     for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) { | 
 | 5225 |         port->channel_masks[i] = mChannelMasks[i]; | 
 | 5226 |     } | 
 | 5227 |     port->num_channel_masks = i; | 
 | 5228 |     for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) { | 
 | 5229 |         port->formats[i] = mFormats[i]; | 
 | 5230 |     } | 
 | 5231 |     port->num_formats = i; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 5232 |  | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 5233 |     ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 5234 |  | 
 | 5235 |     for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { | 
 | 5236 |         port->gains[i] = mGains[i]->mGain; | 
 | 5237 |     } | 
 | 5238 |     port->num_gains = i; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5239 | } | 
 | 5240 |  | 
 | 5241 |  | 
 | 5242 | void AudioPolicyManager::AudioPort::loadSamplingRates(char *name) | 
 | 5243 | { | 
 | 5244 |     char *str = strtok(name, "|"); | 
 | 5245 |  | 
 | 5246 |     // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling | 
 | 5247 |     // rates should be read from the output stream after it is opened for the first time | 
 | 5248 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5249 |         mSamplingRates.add(0); | 
 | 5250 |         return; | 
 | 5251 |     } | 
 | 5252 |  | 
 | 5253 |     while (str != NULL) { | 
 | 5254 |         uint32_t rate = atoi(str); | 
 | 5255 |         if (rate != 0) { | 
 | 5256 |             ALOGV("loadSamplingRates() adding rate %d", rate); | 
 | 5257 |             mSamplingRates.add(rate); | 
 | 5258 |         } | 
 | 5259 |         str = strtok(NULL, "|"); | 
 | 5260 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5261 | } | 
 | 5262 |  | 
 | 5263 | void AudioPolicyManager::AudioPort::loadFormats(char *name) | 
 | 5264 | { | 
 | 5265 |     char *str = strtok(name, "|"); | 
 | 5266 |  | 
 | 5267 |     // by convention, "0' in the first entry in mFormats indicates the supported formats | 
 | 5268 |     // should be read from the output stream after it is opened for the first time | 
 | 5269 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5270 |         mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 5271 |         return; | 
 | 5272 |     } | 
 | 5273 |  | 
 | 5274 |     while (str != NULL) { | 
 | 5275 |         audio_format_t format = (audio_format_t)stringToEnum(sFormatNameToEnumTable, | 
 | 5276 |                                                              ARRAY_SIZE(sFormatNameToEnumTable), | 
 | 5277 |                                                              str); | 
 | 5278 |         if (format != AUDIO_FORMAT_DEFAULT) { | 
 | 5279 |             mFormats.add(format); | 
 | 5280 |         } | 
 | 5281 |         str = strtok(NULL, "|"); | 
 | 5282 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5283 | } | 
 | 5284 |  | 
 | 5285 | void AudioPolicyManager::AudioPort::loadInChannels(char *name) | 
 | 5286 | { | 
 | 5287 |     const char *str = strtok(name, "|"); | 
 | 5288 |  | 
 | 5289 |     ALOGV("loadInChannels() %s", name); | 
 | 5290 |  | 
 | 5291 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5292 |         mChannelMasks.add(0); | 
 | 5293 |         return; | 
 | 5294 |     } | 
 | 5295 |  | 
 | 5296 |     while (str != NULL) { | 
 | 5297 |         audio_channel_mask_t channelMask = | 
 | 5298 |                 (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, | 
 | 5299 |                                                    ARRAY_SIZE(sInChannelsNameToEnumTable), | 
 | 5300 |                                                    str); | 
 | 5301 |         if (channelMask != 0) { | 
 | 5302 |             ALOGV("loadInChannels() adding channelMask %04x", channelMask); | 
 | 5303 |             mChannelMasks.add(channelMask); | 
 | 5304 |         } | 
 | 5305 |         str = strtok(NULL, "|"); | 
 | 5306 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5307 | } | 
 | 5308 |  | 
 | 5309 | void AudioPolicyManager::AudioPort::loadOutChannels(char *name) | 
 | 5310 | { | 
 | 5311 |     const char *str = strtok(name, "|"); | 
 | 5312 |  | 
 | 5313 |     ALOGV("loadOutChannels() %s", name); | 
 | 5314 |  | 
 | 5315 |     // by convention, "0' in the first entry in mChannelMasks indicates the supported channel | 
 | 5316 |     // masks should be read from the output stream after it is opened for the first time | 
 | 5317 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5318 |         mChannelMasks.add(0); | 
 | 5319 |         return; | 
 | 5320 |     } | 
 | 5321 |  | 
 | 5322 |     while (str != NULL) { | 
 | 5323 |         audio_channel_mask_t channelMask = | 
 | 5324 |                 (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, | 
 | 5325 |                                                    ARRAY_SIZE(sOutChannelsNameToEnumTable), | 
 | 5326 |                                                    str); | 
 | 5327 |         if (channelMask != 0) { | 
 | 5328 |             mChannelMasks.add(channelMask); | 
 | 5329 |         } | 
 | 5330 |         str = strtok(NULL, "|"); | 
 | 5331 |     } | 
 | 5332 |     return; | 
 | 5333 | } | 
 | 5334 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5335 | audio_gain_mode_t AudioPolicyManager::AudioPort::loadGainMode(char *name) | 
 | 5336 | { | 
 | 5337 |     const char *str = strtok(name, "|"); | 
 | 5338 |  | 
 | 5339 |     ALOGV("loadGainMode() %s", name); | 
 | 5340 |     audio_gain_mode_t mode = 0; | 
 | 5341 |     while (str != NULL) { | 
 | 5342 |         mode |= (audio_gain_mode_t)stringToEnum(sGainModeNameToEnumTable, | 
 | 5343 |                                                 ARRAY_SIZE(sGainModeNameToEnumTable), | 
 | 5344 |                                                 str); | 
 | 5345 |         str = strtok(NULL, "|"); | 
 | 5346 |     } | 
 | 5347 |     return mode; | 
 | 5348 | } | 
 | 5349 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5350 | void AudioPolicyManager::AudioPort::loadGain(cnode *root, int index) | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5351 | { | 
 | 5352 |     cnode *node = root->first_child; | 
 | 5353 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5354 |     sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5355 |  | 
 | 5356 |     while (node) { | 
 | 5357 |         if (strcmp(node->name, GAIN_MODE) == 0) { | 
 | 5358 |             gain->mGain.mode = loadGainMode((char *)node->value); | 
 | 5359 |         } else if (strcmp(node->name, GAIN_CHANNELS) == 0) { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5360 |             if (mUseInChannelMask) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5361 |                 gain->mGain.channel_mask = | 
 | 5362 |                         (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, | 
 | 5363 |                                                            ARRAY_SIZE(sInChannelsNameToEnumTable), | 
 | 5364 |                                                            (char *)node->value); | 
 | 5365 |             } else { | 
 | 5366 |                 gain->mGain.channel_mask = | 
 | 5367 |                         (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, | 
 | 5368 |                                                            ARRAY_SIZE(sOutChannelsNameToEnumTable), | 
 | 5369 |                                                            (char *)node->value); | 
 | 5370 |             } | 
 | 5371 |         } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) { | 
 | 5372 |             gain->mGain.min_value = atoi((char *)node->value); | 
 | 5373 |         } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) { | 
 | 5374 |             gain->mGain.max_value = atoi((char *)node->value); | 
 | 5375 |         } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) { | 
 | 5376 |             gain->mGain.default_value = atoi((char *)node->value); | 
 | 5377 |         } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) { | 
 | 5378 |             gain->mGain.step_value = atoi((char *)node->value); | 
 | 5379 |         } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) { | 
 | 5380 |             gain->mGain.min_ramp_ms = atoi((char *)node->value); | 
 | 5381 |         } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) { | 
 | 5382 |             gain->mGain.max_ramp_ms = atoi((char *)node->value); | 
 | 5383 |         } | 
 | 5384 |         node = node->next; | 
 | 5385 |     } | 
 | 5386 |  | 
 | 5387 |     ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d", | 
 | 5388 |           gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value); | 
 | 5389 |  | 
 | 5390 |     if (gain->mGain.mode == 0) { | 
 | 5391 |         return; | 
 | 5392 |     } | 
 | 5393 |     mGains.add(gain); | 
 | 5394 | } | 
 | 5395 |  | 
 | 5396 | void AudioPolicyManager::AudioPort::loadGains(cnode *root) | 
 | 5397 | { | 
 | 5398 |     cnode *node = root->first_child; | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5399 |     int index = 0; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5400 |     while (node) { | 
 | 5401 |         ALOGV("loadGains() loading gain %s", node->name); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5402 |         loadGain(node, index++); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5403 |         node = node->next; | 
 | 5404 |     } | 
 | 5405 | } | 
 | 5406 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5407 | status_t AudioPolicyManager::AudioPort::checkExactSamplingRate(uint32_t samplingRate) const | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5408 | { | 
 | 5409 |     for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 5410 |         if (mSamplingRates[i] == samplingRate) { | 
 | 5411 |             return NO_ERROR; | 
 | 5412 |         } | 
 | 5413 |     } | 
 | 5414 |     return BAD_VALUE; | 
 | 5415 | } | 
 | 5416 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5417 | status_t AudioPolicyManager::AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate, | 
 | 5418 |         uint32_t *updatedSamplingRate) const | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5419 | { | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5420 |     // Search for the closest supported sampling rate that is above (preferred) | 
 | 5421 |     // or below (acceptable) the desired sampling rate, within a permitted ratio. | 
 | 5422 |     // The sampling rates do not need to be sorted in ascending order. | 
 | 5423 |     ssize_t maxBelow = -1; | 
 | 5424 |     ssize_t minAbove = -1; | 
 | 5425 |     uint32_t candidate; | 
 | 5426 |     for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
 | 5427 |         candidate = mSamplingRates[i]; | 
 | 5428 |         if (candidate == samplingRate) { | 
 | 5429 |             if (updatedSamplingRate != NULL) { | 
 | 5430 |                 *updatedSamplingRate = candidate; | 
 | 5431 |             } | 
 | 5432 |             return NO_ERROR; | 
 | 5433 |         } | 
 | 5434 |         // candidate < desired | 
 | 5435 |         if (candidate < samplingRate) { | 
 | 5436 |             if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) { | 
 | 5437 |                 maxBelow = i; | 
 | 5438 |             } | 
 | 5439 |         // candidate > desired | 
 | 5440 |         } else { | 
 | 5441 |             if (minAbove < 0 || candidate < mSamplingRates[minAbove]) { | 
 | 5442 |                 minAbove = i; | 
 | 5443 |             } | 
 | 5444 |         } | 
 | 5445 |     } | 
 | 5446 |     // This uses hard-coded knowledge about AudioFlinger resampling ratios. | 
 | 5447 |     // TODO Move these assumptions out. | 
 | 5448 |     static const uint32_t kMaxDownSampleRatio = 6;  // beyond this aliasing occurs | 
 | 5449 |     static const uint32_t kMaxUpSampleRatio = 256;  // beyond this sample rate inaccuracies occur | 
 | 5450 |                                                     // due to approximation by an int32_t of the | 
 | 5451 |                                                     // phase increments | 
 | 5452 |     // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. | 
 | 5453 |     if (minAbove >= 0) { | 
 | 5454 |         candidate = mSamplingRates[minAbove]; | 
 | 5455 |         if (candidate / kMaxDownSampleRatio <= samplingRate) { | 
 | 5456 |             if (updatedSamplingRate != NULL) { | 
 | 5457 |                 *updatedSamplingRate = candidate; | 
 | 5458 |             } | 
 | 5459 |             return NO_ERROR; | 
 | 5460 |         } | 
 | 5461 |     } | 
 | 5462 |     // But if we have to up-sample from a lower sampling rate, that's OK. | 
 | 5463 |     if (maxBelow >= 0) { | 
 | 5464 |         candidate = mSamplingRates[maxBelow]; | 
 | 5465 |         if (candidate * kMaxUpSampleRatio >= samplingRate) { | 
 | 5466 |             if (updatedSamplingRate != NULL) { | 
 | 5467 |                 *updatedSamplingRate = candidate; | 
 | 5468 |             } | 
 | 5469 |             return NO_ERROR; | 
 | 5470 |         } | 
 | 5471 |     } | 
 | 5472 |     // leave updatedSamplingRate unmodified | 
 | 5473 |     return BAD_VALUE; | 
 | 5474 | } | 
 | 5475 |  | 
 | 5476 | status_t AudioPolicyManager::AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const | 
 | 5477 | { | 
 | 5478 |     for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5479 |         if (mChannelMasks[i] == channelMask) { | 
 | 5480 |             return NO_ERROR; | 
 | 5481 |         } | 
 | 5482 |     } | 
 | 5483 |     return BAD_VALUE; | 
 | 5484 | } | 
 | 5485 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5486 | status_t AudioPolicyManager::AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask) | 
 | 5487 |         const | 
 | 5488 | { | 
 | 5489 |     const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; | 
 | 5490 |     for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 5491 |         // FIXME Does not handle multi-channel automatic conversions yet | 
 | 5492 |         audio_channel_mask_t supported = mChannelMasks[i]; | 
 | 5493 |         if (supported == channelMask) { | 
 | 5494 |             return NO_ERROR; | 
 | 5495 |         } | 
 | 5496 |         if (isRecordThread) { | 
 | 5497 |             // This uses hard-coded knowledge that AudioFlinger can silently down-mix and up-mix. | 
 | 5498 |             // FIXME Abstract this out to a table. | 
 | 5499 |             if (((supported == AUDIO_CHANNEL_IN_FRONT_BACK || supported == AUDIO_CHANNEL_IN_STEREO) | 
 | 5500 |                     && channelMask == AUDIO_CHANNEL_IN_MONO) || | 
 | 5501 |                 (supported == AUDIO_CHANNEL_IN_MONO && (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK | 
 | 5502 |                     || channelMask == AUDIO_CHANNEL_IN_STEREO))) { | 
 | 5503 |                 return NO_ERROR; | 
 | 5504 |             } | 
 | 5505 |         } | 
 | 5506 |     } | 
 | 5507 |     return BAD_VALUE; | 
 | 5508 | } | 
 | 5509 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5510 | status_t AudioPolicyManager::AudioPort::checkFormat(audio_format_t format) const | 
 | 5511 | { | 
 | 5512 |     for (size_t i = 0; i < mFormats.size(); i ++) { | 
 | 5513 |         if (mFormats[i] == format) { | 
 | 5514 |             return NO_ERROR; | 
 | 5515 |         } | 
 | 5516 |     } | 
 | 5517 |     return BAD_VALUE; | 
 | 5518 | } | 
 | 5519 |  | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5520 |  | 
 | 5521 | uint32_t AudioPolicyManager::AudioPort::pickSamplingRate() const | 
 | 5522 | { | 
 | 5523 |     // special case for uninitialized dynamic profile | 
 | 5524 |     if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) { | 
 | 5525 |         return 0; | 
 | 5526 |     } | 
 | 5527 |  | 
 | 5528 |     uint32_t samplingRate = 0; | 
 | 5529 |     uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; | 
 | 5530 |  | 
 | 5531 |     // For mixed output and inputs, use max mixer sampling rates. Do not | 
 | 5532 |     // limit sampling rate otherwise | 
 | 5533 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 5534 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 5535 |             (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)))) { | 
 | 5536 |         maxRate = UINT_MAX; | 
 | 5537 |     } | 
 | 5538 |     for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 5539 |         if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) { | 
 | 5540 |             samplingRate = mSamplingRates[i]; | 
 | 5541 |         } | 
 | 5542 |     } | 
 | 5543 |     return samplingRate; | 
 | 5544 | } | 
 | 5545 |  | 
 | 5546 | audio_channel_mask_t AudioPolicyManager::AudioPort::pickChannelMask() const | 
 | 5547 | { | 
 | 5548 |     // special case for uninitialized dynamic profile | 
 | 5549 |     if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) { | 
 | 5550 |         return AUDIO_CHANNEL_NONE; | 
 | 5551 |     } | 
 | 5552 |  | 
 | 5553 |     audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE; | 
 | 5554 |     uint32_t channelCount = 0; | 
 | 5555 |     uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; | 
 | 5556 |  | 
 | 5557 |     // For mixed output and inputs, use max mixer channel count. Do not | 
 | 5558 |     // limit channel count otherwise | 
 | 5559 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 5560 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 5561 |             (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)))) { | 
 | 5562 |         maxCount = UINT_MAX; | 
 | 5563 |     } | 
 | 5564 |     for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 5565 |         uint32_t cnlCount; | 
 | 5566 |         if (mUseInChannelMask) { | 
 | 5567 |             cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); | 
 | 5568 |         } else { | 
 | 5569 |             cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); | 
 | 5570 |         } | 
 | 5571 |         if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { | 
 | 5572 |             channelMask = mChannelMasks[i]; | 
 | 5573 |         } | 
 | 5574 |     } | 
 | 5575 |     return channelMask; | 
 | 5576 | } | 
 | 5577 |  | 
| Andy Hung | 9a60538 | 2014-07-28 16:16:31 -0700 | [diff] [blame] | 5578 | /* format in order of increasing preference */ | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5579 | const audio_format_t AudioPolicyManager::AudioPort::sPcmFormatCompareTable[] = { | 
 | 5580 |         AUDIO_FORMAT_DEFAULT, | 
 | 5581 |         AUDIO_FORMAT_PCM_16_BIT, | 
| Eric Laurent | a204994 | 2014-07-21 17:49:25 -0700 | [diff] [blame] | 5582 |         AUDIO_FORMAT_PCM_8_24_BIT, | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5583 |         AUDIO_FORMAT_PCM_24_BIT_PACKED, | 
| Eric Laurent | a204994 | 2014-07-21 17:49:25 -0700 | [diff] [blame] | 5584 |         AUDIO_FORMAT_PCM_32_BIT, | 
| Andy Hung | 9a60538 | 2014-07-28 16:16:31 -0700 | [diff] [blame] | 5585 |         AUDIO_FORMAT_PCM_FLOAT, | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5586 | }; | 
 | 5587 |  | 
 | 5588 | int AudioPolicyManager::AudioPort::compareFormats(audio_format_t format1, | 
 | 5589 |                                                   audio_format_t format2) | 
 | 5590 | { | 
 | 5591 |     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any | 
 | 5592 |     // compressed format and better than any PCM format. This is by design of pickFormat() | 
 | 5593 |     if (!audio_is_linear_pcm(format1)) { | 
 | 5594 |         if (!audio_is_linear_pcm(format2)) { | 
 | 5595 |             return 0; | 
 | 5596 |         } | 
 | 5597 |         return 1; | 
 | 5598 |     } | 
 | 5599 |     if (!audio_is_linear_pcm(format2)) { | 
 | 5600 |         return -1; | 
 | 5601 |     } | 
 | 5602 |  | 
 | 5603 |     int index1 = -1, index2 = -1; | 
 | 5604 |     for (size_t i = 0; | 
 | 5605 |             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); | 
 | 5606 |             i ++) { | 
 | 5607 |         if (sPcmFormatCompareTable[i] == format1) { | 
 | 5608 |             index1 = i; | 
 | 5609 |         } | 
 | 5610 |         if (sPcmFormatCompareTable[i] == format2) { | 
 | 5611 |             index2 = i; | 
 | 5612 |         } | 
 | 5613 |     } | 
 | 5614 |     // format1 not found => index1 < 0 => format2 > format1 | 
 | 5615 |     // format2 not found => index2 < 0 => format2 < format1 | 
 | 5616 |     return index1 - index2; | 
 | 5617 | } | 
 | 5618 |  | 
 | 5619 | audio_format_t AudioPolicyManager::AudioPort::pickFormat() const | 
 | 5620 | { | 
 | 5621 |     // special case for uninitialized dynamic profile | 
 | 5622 |     if (mFormats.size() == 1 && mFormats[0] == 0) { | 
 | 5623 |         return AUDIO_FORMAT_DEFAULT; | 
 | 5624 |     } | 
 | 5625 |  | 
 | 5626 |     audio_format_t format = AUDIO_FORMAT_DEFAULT; | 
| Andy Hung | 9a60538 | 2014-07-28 16:16:31 -0700 | [diff] [blame] | 5627 |     audio_format_t bestFormat = | 
 | 5628 |             AudioPolicyManager::AudioPort::sPcmFormatCompareTable[ | 
 | 5629 |                 ARRAY_SIZE(AudioPolicyManager::AudioPort::sPcmFormatCompareTable) - 1]; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5630 |     // For mixed output and inputs, use best mixer output format. Do not | 
 | 5631 |     // limit format otherwise | 
 | 5632 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 5633 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
| Eric Laurent | d862237 | 2014-07-27 13:47:31 -0700 | [diff] [blame] | 5634 |              (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5635 |         bestFormat = AUDIO_FORMAT_INVALID; | 
 | 5636 |     } | 
 | 5637 |  | 
 | 5638 |     for (size_t i = 0; i < mFormats.size(); i ++) { | 
 | 5639 |         if ((compareFormats(mFormats[i], format) > 0) && | 
 | 5640 |                 (compareFormats(mFormats[i], bestFormat) <= 0)) { | 
 | 5641 |             format = mFormats[i]; | 
 | 5642 |         } | 
 | 5643 |     } | 
 | 5644 |     return format; | 
 | 5645 | } | 
 | 5646 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5647 | status_t AudioPolicyManager::AudioPort::checkGain(const struct audio_gain_config *gainConfig, | 
 | 5648 |                                                   int index) const | 
 | 5649 | { | 
 | 5650 |     if (index < 0 || (size_t)index >= mGains.size()) { | 
 | 5651 |         return BAD_VALUE; | 
 | 5652 |     } | 
 | 5653 |     return mGains[index]->checkConfig(gainConfig); | 
 | 5654 | } | 
 | 5655 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5656 | void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const | 
 | 5657 | { | 
 | 5658 |     const size_t SIZE = 256; | 
 | 5659 |     char buffer[SIZE]; | 
 | 5660 |     String8 result; | 
 | 5661 |  | 
 | 5662 |     if (mName.size() != 0) { | 
 | 5663 |         snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); | 
 | 5664 |         result.append(buffer); | 
 | 5665 |     } | 
 | 5666 |  | 
 | 5667 |     if (mSamplingRates.size() != 0) { | 
 | 5668 |         snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); | 
 | 5669 |         result.append(buffer); | 
 | 5670 |         for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5671 |             if (i == 0 && mSamplingRates[i] == 0) { | 
 | 5672 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 5673 |             } else { | 
 | 5674 |                 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); | 
 | 5675 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5676 |             result.append(buffer); | 
 | 5677 |             result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); | 
 | 5678 |         } | 
 | 5679 |         result.append("\n"); | 
 | 5680 |     } | 
 | 5681 |  | 
 | 5682 |     if (mChannelMasks.size() != 0) { | 
 | 5683 |         snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); | 
 | 5684 |         result.append(buffer); | 
 | 5685 |         for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5686 |             ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]); | 
 | 5687 |  | 
 | 5688 |             if (i == 0 && mChannelMasks[i] == 0) { | 
 | 5689 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 5690 |             } else { | 
 | 5691 |                 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); | 
 | 5692 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5693 |             result.append(buffer); | 
 | 5694 |             result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); | 
 | 5695 |         } | 
 | 5696 |         result.append("\n"); | 
 | 5697 |     } | 
 | 5698 |  | 
 | 5699 |     if (mFormats.size() != 0) { | 
 | 5700 |         snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); | 
 | 5701 |         result.append(buffer); | 
 | 5702 |         for (size_t i = 0; i < mFormats.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5703 |             const char *formatStr = enumToString(sFormatNameToEnumTable, | 
 | 5704 |                                                  ARRAY_SIZE(sFormatNameToEnumTable), | 
 | 5705 |                                                  mFormats[i]); | 
 | 5706 |             if (i == 0 && strcmp(formatStr, "") == 0) { | 
 | 5707 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 5708 |             } else { | 
| Eric Laurent | cf2c021 | 2014-07-25 16:20:43 -0700 | [diff] [blame] | 5709 |                 snprintf(buffer, SIZE, "%s", formatStr); | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5710 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5711 |             result.append(buffer); | 
 | 5712 |             result.append(i == (mFormats.size() - 1) ? "" : ", "); | 
 | 5713 |         } | 
 | 5714 |         result.append("\n"); | 
 | 5715 |     } | 
 | 5716 |     write(fd, result.string(), result.size()); | 
 | 5717 |     if (mGains.size() != 0) { | 
 | 5718 |         snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); | 
 | 5719 |         write(fd, buffer, strlen(buffer) + 1); | 
 | 5720 |         result.append(buffer); | 
 | 5721 |         for (size_t i = 0; i < mGains.size(); i++) { | 
 | 5722 |             mGains[i]->dump(fd, spaces + 2, i); | 
 | 5723 |         } | 
 | 5724 |     } | 
 | 5725 | } | 
 | 5726 |  | 
 | 5727 | // --- AudioGain class implementation | 
 | 5728 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5729 | AudioPolicyManager::AudioGain::AudioGain(int index, bool useInChannelMask) | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5730 | { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5731 |     mIndex = index; | 
 | 5732 |     mUseInChannelMask = useInChannelMask; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5733 |     memset(&mGain, 0, sizeof(struct audio_gain)); | 
 | 5734 | } | 
 | 5735 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5736 | void AudioPolicyManager::AudioGain::getDefaultConfig(struct audio_gain_config *config) | 
 | 5737 | { | 
 | 5738 |     config->index = mIndex; | 
 | 5739 |     config->mode = mGain.mode; | 
 | 5740 |     config->channel_mask = mGain.channel_mask; | 
 | 5741 |     if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { | 
 | 5742 |         config->values[0] = mGain.default_value; | 
 | 5743 |     } else { | 
 | 5744 |         uint32_t numValues; | 
 | 5745 |         if (mUseInChannelMask) { | 
 | 5746 |             numValues = audio_channel_count_from_in_mask(mGain.channel_mask); | 
 | 5747 |         } else { | 
 | 5748 |             numValues = audio_channel_count_from_out_mask(mGain.channel_mask); | 
 | 5749 |         } | 
 | 5750 |         for (size_t i = 0; i < numValues; i++) { | 
 | 5751 |             config->values[i] = mGain.default_value; | 
 | 5752 |         } | 
 | 5753 |     } | 
 | 5754 |     if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { | 
 | 5755 |         config->ramp_duration_ms = mGain.min_ramp_ms; | 
 | 5756 |     } | 
 | 5757 | } | 
 | 5758 |  | 
 | 5759 | status_t AudioPolicyManager::AudioGain::checkConfig(const struct audio_gain_config *config) | 
 | 5760 | { | 
 | 5761 |     if ((config->mode & ~mGain.mode) != 0) { | 
 | 5762 |         return BAD_VALUE; | 
 | 5763 |     } | 
 | 5764 |     if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { | 
 | 5765 |         if ((config->values[0] < mGain.min_value) || | 
 | 5766 |                     (config->values[0] > mGain.max_value)) { | 
 | 5767 |             return BAD_VALUE; | 
 | 5768 |         } | 
 | 5769 |     } else { | 
 | 5770 |         if ((config->channel_mask & ~mGain.channel_mask) != 0) { | 
 | 5771 |             return BAD_VALUE; | 
 | 5772 |         } | 
 | 5773 |         uint32_t numValues; | 
 | 5774 |         if (mUseInChannelMask) { | 
 | 5775 |             numValues = audio_channel_count_from_in_mask(config->channel_mask); | 
 | 5776 |         } else { | 
 | 5777 |             numValues = audio_channel_count_from_out_mask(config->channel_mask); | 
 | 5778 |         } | 
 | 5779 |         for (size_t i = 0; i < numValues; i++) { | 
 | 5780 |             if ((config->values[i] < mGain.min_value) || | 
 | 5781 |                     (config->values[i] > mGain.max_value)) { | 
 | 5782 |                 return BAD_VALUE; | 
 | 5783 |             } | 
 | 5784 |         } | 
 | 5785 |     } | 
 | 5786 |     if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { | 
 | 5787 |         if ((config->ramp_duration_ms < mGain.min_ramp_ms) || | 
 | 5788 |                     (config->ramp_duration_ms > mGain.max_ramp_ms)) { | 
 | 5789 |             return BAD_VALUE; | 
 | 5790 |         } | 
 | 5791 |     } | 
 | 5792 |     return NO_ERROR; | 
 | 5793 | } | 
 | 5794 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5795 | void AudioPolicyManager::AudioGain::dump(int fd, int spaces, int index) const | 
 | 5796 | { | 
 | 5797 |     const size_t SIZE = 256; | 
 | 5798 |     char buffer[SIZE]; | 
 | 5799 |     String8 result; | 
 | 5800 |  | 
 | 5801 |     snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1); | 
 | 5802 |     result.append(buffer); | 
 | 5803 |     snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode); | 
 | 5804 |     result.append(buffer); | 
 | 5805 |     snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask); | 
 | 5806 |     result.append(buffer); | 
 | 5807 |     snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value); | 
 | 5808 |     result.append(buffer); | 
 | 5809 |     snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value); | 
 | 5810 |     result.append(buffer); | 
 | 5811 |     snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value); | 
 | 5812 |     result.append(buffer); | 
 | 5813 |     snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value); | 
 | 5814 |     result.append(buffer); | 
 | 5815 |     snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms); | 
 | 5816 |     result.append(buffer); | 
 | 5817 |     snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms); | 
 | 5818 |     result.append(buffer); | 
 | 5819 |  | 
 | 5820 |     write(fd, result.string(), result.size()); | 
 | 5821 | } | 
 | 5822 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5823 | // --- AudioPortConfig class implementation | 
 | 5824 |  | 
 | 5825 | AudioPolicyManager::AudioPortConfig::AudioPortConfig() | 
 | 5826 | { | 
 | 5827 |     mSamplingRate = 0; | 
 | 5828 |     mChannelMask = AUDIO_CHANNEL_NONE; | 
 | 5829 |     mFormat = AUDIO_FORMAT_INVALID; | 
 | 5830 |     mGain.index = -1; | 
 | 5831 | } | 
 | 5832 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5833 | status_t AudioPolicyManager::AudioPortConfig::applyAudioPortConfig( | 
 | 5834 |                                                         const struct audio_port_config *config, | 
 | 5835 |                                                         struct audio_port_config *backupConfig) | 
 | 5836 | { | 
 | 5837 |     struct audio_port_config localBackupConfig; | 
 | 5838 |     status_t status = NO_ERROR; | 
 | 5839 |  | 
 | 5840 |     localBackupConfig.config_mask = config->config_mask; | 
 | 5841 |     toAudioPortConfig(&localBackupConfig); | 
 | 5842 |  | 
 | 5843 |     if (mAudioPort == 0) { | 
 | 5844 |         status = NO_INIT; | 
 | 5845 |         goto exit; | 
 | 5846 |     } | 
 | 5847 |     if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5848 |         status = mAudioPort->checkExactSamplingRate(config->sample_rate); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5849 |         if (status != NO_ERROR) { | 
 | 5850 |             goto exit; | 
 | 5851 |         } | 
 | 5852 |         mSamplingRate = config->sample_rate; | 
 | 5853 |     } | 
 | 5854 |     if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5855 |         status = mAudioPort->checkExactChannelMask(config->channel_mask); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5856 |         if (status != NO_ERROR) { | 
 | 5857 |             goto exit; | 
 | 5858 |         } | 
 | 5859 |         mChannelMask = config->channel_mask; | 
 | 5860 |     } | 
 | 5861 |     if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { | 
 | 5862 |         status = mAudioPort->checkFormat(config->format); | 
 | 5863 |         if (status != NO_ERROR) { | 
 | 5864 |             goto exit; | 
 | 5865 |         } | 
 | 5866 |         mFormat = config->format; | 
 | 5867 |     } | 
 | 5868 |     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { | 
 | 5869 |         status = mAudioPort->checkGain(&config->gain, config->gain.index); | 
 | 5870 |         if (status != NO_ERROR) { | 
 | 5871 |             goto exit; | 
 | 5872 |         } | 
 | 5873 |         mGain = config->gain; | 
 | 5874 |     } | 
 | 5875 |  | 
 | 5876 | exit: | 
 | 5877 |     if (status != NO_ERROR) { | 
 | 5878 |         applyAudioPortConfig(&localBackupConfig); | 
 | 5879 |     } | 
 | 5880 |     if (backupConfig != NULL) { | 
 | 5881 |         *backupConfig = localBackupConfig; | 
 | 5882 |     } | 
 | 5883 |     return status; | 
 | 5884 | } | 
 | 5885 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5886 | void AudioPolicyManager::AudioPortConfig::toAudioPortConfig( | 
 | 5887 |                                                     struct audio_port_config *dstConfig, | 
 | 5888 |                                                     const struct audio_port_config *srcConfig) const | 
 | 5889 | { | 
 | 5890 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { | 
 | 5891 |         dstConfig->sample_rate = mSamplingRate; | 
 | 5892 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { | 
 | 5893 |             dstConfig->sample_rate = srcConfig->sample_rate; | 
 | 5894 |         } | 
 | 5895 |     } else { | 
 | 5896 |         dstConfig->sample_rate = 0; | 
 | 5897 |     } | 
 | 5898 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { | 
 | 5899 |         dstConfig->channel_mask = mChannelMask; | 
 | 5900 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { | 
 | 5901 |             dstConfig->channel_mask = srcConfig->channel_mask; | 
 | 5902 |         } | 
 | 5903 |     } else { | 
 | 5904 |         dstConfig->channel_mask = AUDIO_CHANNEL_NONE; | 
 | 5905 |     } | 
 | 5906 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { | 
 | 5907 |         dstConfig->format = mFormat; | 
 | 5908 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { | 
 | 5909 |             dstConfig->format = srcConfig->format; | 
 | 5910 |         } | 
 | 5911 |     } else { | 
 | 5912 |         dstConfig->format = AUDIO_FORMAT_INVALID; | 
 | 5913 |     } | 
 | 5914 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) { | 
 | 5915 |         dstConfig->gain = mGain; | 
 | 5916 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) { | 
 | 5917 |             dstConfig->gain = srcConfig->gain; | 
 | 5918 |         } | 
 | 5919 |     } else { | 
 | 5920 |         dstConfig->gain.index = -1; | 
 | 5921 |     } | 
 | 5922 |     if (dstConfig->gain.index != -1) { | 
 | 5923 |         dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; | 
 | 5924 |     } else { | 
 | 5925 |         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; | 
 | 5926 |     } | 
 | 5927 | } | 
 | 5928 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5929 | // --- IOProfile class implementation | 
 | 5930 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5931 | AudioPolicyManager::IOProfile::IOProfile(const String8& name, audio_port_role_t role, | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5932 |                                          const sp<HwModule>& module) | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5933 |     : AudioPort(name, AUDIO_PORT_TYPE_MIX, role, module) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5934 | { | 
 | 5935 | } | 
 | 5936 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5937 | AudioPolicyManager::IOProfile::~IOProfile() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5938 | { | 
 | 5939 | } | 
 | 5940 |  | 
 | 5941 | // checks if the IO profile is compatible with specified parameters. | 
 | 5942 | // Sampling rate, format and channel mask must be specified in order to | 
 | 5943 | // get a valid a match | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5944 | bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5945 |                                                             uint32_t samplingRate, | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5946 |                                                             uint32_t *updatedSamplingRate, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5947 |                                                             audio_format_t format, | 
 | 5948 |                                                             audio_channel_mask_t channelMask, | 
 | 5949 |                                                             audio_output_flags_t flags) const | 
 | 5950 | { | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5951 |     const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE; | 
 | 5952 |     const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK; | 
 | 5953 |     ALOG_ASSERT(isPlaybackThread != isRecordThread); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5954 |  | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5955 |     if ((mSupportedDevices.types() & device) != device) { | 
 | 5956 |         return false; | 
 | 5957 |     } | 
 | 5958 |  | 
 | 5959 |     if (samplingRate == 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5960 |          return false; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5961 |     } | 
 | 5962 |     uint32_t myUpdatedSamplingRate = samplingRate; | 
 | 5963 |     if (isPlaybackThread && checkExactSamplingRate(samplingRate) != NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5964 |          return false; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5965 |     } | 
 | 5966 |     if (isRecordThread && checkCompatibleSamplingRate(samplingRate, &myUpdatedSamplingRate) != | 
 | 5967 |             NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5968 |          return false; | 
| Glenn Kasten | cbd4802 | 2014-07-24 13:46:44 -0700 | [diff] [blame] | 5969 |     } | 
 | 5970 |  | 
 | 5971 |     if (!audio_is_valid_format(format) || checkFormat(format) != NO_ERROR) { | 
 | 5972 |         return false; | 
 | 5973 |     } | 
 | 5974 |  | 
 | 5975 |     if (isPlaybackThread && (!audio_is_output_channel(channelMask) || | 
 | 5976 |             checkExactChannelMask(channelMask) != NO_ERROR)) { | 
 | 5977 |         return false; | 
 | 5978 |     } | 
 | 5979 |     if (isRecordThread && (!audio_is_input_channel(channelMask) || | 
 | 5980 |             checkCompatibleChannelMask(channelMask) != NO_ERROR)) { | 
 | 5981 |         return false; | 
 | 5982 |     } | 
 | 5983 |  | 
 | 5984 |     if (isPlaybackThread && (mFlags & flags) != flags) { | 
 | 5985 |         return false; | 
 | 5986 |     } | 
 | 5987 |     // The only input flag that is allowed to be different is the fast flag. | 
 | 5988 |     // An existing fast stream is compatible with a normal track request. | 
 | 5989 |     // An existing normal stream is compatible with a fast track request, | 
 | 5990 |     // but the fast request will be denied by AudioFlinger and converted to normal track. | 
 | 5991 |     if (isRecordThread && (((audio_input_flags_t) mFlags ^ (audio_input_flags_t) flags) & | 
 | 5992 |             ~AUDIO_INPUT_FLAG_FAST)) { | 
 | 5993 |         return false; | 
 | 5994 |     } | 
 | 5995 |  | 
 | 5996 |     if (updatedSamplingRate != NULL) { | 
 | 5997 |         *updatedSamplingRate = myUpdatedSamplingRate; | 
 | 5998 |     } | 
 | 5999 |     return true; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6000 | } | 
 | 6001 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6002 | void AudioPolicyManager::IOProfile::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6003 | { | 
 | 6004 |     const size_t SIZE = 256; | 
 | 6005 |     char buffer[SIZE]; | 
 | 6006 |     String8 result; | 
 | 6007 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6008 |     AudioPort::dump(fd, 4); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6009 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6010 |     snprintf(buffer, SIZE, "    - flags: 0x%04x\n", mFlags); | 
 | 6011 |     result.append(buffer); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6012 |     snprintf(buffer, SIZE, "    - devices:\n"); | 
 | 6013 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6014 |     write(fd, result.string(), result.size()); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6015 |     for (size_t i = 0; i < mSupportedDevices.size(); i++) { | 
 | 6016 |         mSupportedDevices[i]->dump(fd, 6, i); | 
 | 6017 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6018 | } | 
 | 6019 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 6020 | void AudioPolicyManager::IOProfile::log() | 
 | 6021 | { | 
 | 6022 |     const size_t SIZE = 256; | 
 | 6023 |     char buffer[SIZE]; | 
 | 6024 |     String8 result; | 
 | 6025 |  | 
 | 6026 |     ALOGV("    - sampling rates: "); | 
 | 6027 |     for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
 | 6028 |         ALOGV("  %d", mSamplingRates[i]); | 
 | 6029 |     } | 
 | 6030 |  | 
 | 6031 |     ALOGV("    - channel masks: "); | 
 | 6032 |     for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
 | 6033 |         ALOGV("  0x%04x", mChannelMasks[i]); | 
 | 6034 |     } | 
 | 6035 |  | 
 | 6036 |     ALOGV("    - formats: "); | 
 | 6037 |     for (size_t i = 0; i < mFormats.size(); i++) { | 
 | 6038 |         ALOGV("  0x%08x", mFormats[i]); | 
 | 6039 |     } | 
 | 6040 |  | 
 | 6041 |     ALOGV("    - devices: 0x%04x\n", mSupportedDevices.types()); | 
 | 6042 |     ALOGV("    - flags: 0x%04x\n", mFlags); | 
 | 6043 | } | 
 | 6044 |  | 
 | 6045 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6046 | // --- DeviceDescriptor implementation | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6047 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6048 |  | 
 | 6049 | AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) : | 
 | 6050 |                      AudioPort(name, AUDIO_PORT_TYPE_DEVICE, | 
 | 6051 |                                audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : | 
 | 6052 |                                                               AUDIO_PORT_ROLE_SOURCE, | 
 | 6053 |                              NULL), | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 6054 |                      mDeviceType(type), mAddress(""), mId(0) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6055 | { | 
 | 6056 |     mAudioPort = this; | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 6057 |     if (mGains.size() > 0) { | 
 | 6058 |         mGains[0]->getDefaultConfig(&mGain); | 
 | 6059 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6060 | } | 
 | 6061 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6062 | bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6063 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6064 |     // Devices are considered equal if they: | 
 | 6065 |     // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE) | 
 | 6066 |     // - have the same address or one device does not specify the address | 
 | 6067 |     // - 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] | 6068 |     return (mDeviceType == other->mDeviceType) && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6069 |            (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) && | 
| Eric Laurent | 2f8a36f | 2014-03-26 19:05:55 -0700 | [diff] [blame] | 6070 |            (mChannelMask == 0 || other->mChannelMask == 0 || | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6071 |                 mChannelMask == other->mChannelMask); | 
 | 6072 | } | 
 | 6073 |  | 
 | 6074 | void AudioPolicyManager::DeviceVector::refreshTypes() | 
 | 6075 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6076 |     mDeviceTypes = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6077 |     for(size_t i = 0; i < size(); i++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6078 |         mDeviceTypes |= itemAt(i)->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6079 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6080 |     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6081 | } | 
 | 6082 |  | 
 | 6083 | ssize_t AudioPolicyManager::DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const | 
 | 6084 | { | 
 | 6085 |     for(size_t i = 0; i < size(); i++) { | 
 | 6086 |         if (item->equals(itemAt(i))) { | 
 | 6087 |             return i; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6088 |         } | 
 | 6089 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6090 |     return -1; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6091 | } | 
 | 6092 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6093 | ssize_t AudioPolicyManager::DeviceVector::add(const sp<DeviceDescriptor>& item) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6094 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6095 |     ssize_t ret = indexOf(item); | 
 | 6096 |  | 
 | 6097 |     if (ret < 0) { | 
 | 6098 |         ret = SortedVector::add(item); | 
 | 6099 |         if (ret >= 0) { | 
 | 6100 |             refreshTypes(); | 
 | 6101 |         } | 
 | 6102 |     } else { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6103 |         ALOGW("DeviceVector::add device %08x already in", item->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6104 |         ret = -1; | 
 | 6105 |     } | 
 | 6106 |     return ret; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6107 | } | 
 | 6108 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6109 | ssize_t AudioPolicyManager::DeviceVector::remove(const sp<DeviceDescriptor>& item) | 
 | 6110 | { | 
 | 6111 |     size_t i; | 
 | 6112 |     ssize_t ret = indexOf(item); | 
 | 6113 |  | 
 | 6114 |     if (ret < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6115 |         ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6116 |     } else { | 
 | 6117 |         ret = SortedVector::removeAt(ret); | 
 | 6118 |         if (ret >= 0) { | 
 | 6119 |             refreshTypes(); | 
 | 6120 |         } | 
 | 6121 |     } | 
 | 6122 |     return ret; | 
 | 6123 | } | 
 | 6124 |  | 
 | 6125 | void AudioPolicyManager::DeviceVector::loadDevicesFromType(audio_devices_t types) | 
 | 6126 | { | 
 | 6127 |     DeviceVector deviceList; | 
 | 6128 |  | 
 | 6129 |     uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types; | 
 | 6130 |     types &= ~role_bit; | 
 | 6131 |  | 
 | 6132 |     while (types) { | 
 | 6133 |         uint32_t i = 31 - __builtin_clz(types); | 
 | 6134 |         uint32_t type = 1 << i; | 
 | 6135 |         types &= ~type; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6136 |         add(new DeviceDescriptor(String8(""), type | role_bit)); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6137 |     } | 
 | 6138 | } | 
 | 6139 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6140 | void AudioPolicyManager::DeviceVector::loadDevicesFromName(char *name, | 
 | 6141 |                                                            const DeviceVector& declaredDevices) | 
 | 6142 | { | 
 | 6143 |     char *devName = strtok(name, "|"); | 
 | 6144 |     while (devName != NULL) { | 
 | 6145 |         if (strlen(devName) != 0) { | 
 | 6146 |             audio_devices_t type = stringToEnum(sDeviceNameToEnumTable, | 
 | 6147 |                                  ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6148 |                                  devName); | 
 | 6149 |             if (type != AUDIO_DEVICE_NONE) { | 
 | 6150 |                 add(new DeviceDescriptor(String8(""), type)); | 
 | 6151 |             } else { | 
 | 6152 |                 sp<DeviceDescriptor> deviceDesc = | 
 | 6153 |                         declaredDevices.getDeviceFromName(String8(devName)); | 
 | 6154 |                 if (deviceDesc != 0) { | 
 | 6155 |                     add(deviceDesc); | 
 | 6156 |                 } | 
 | 6157 |             } | 
 | 6158 |          } | 
 | 6159 |         devName = strtok(NULL, "|"); | 
 | 6160 |      } | 
 | 6161 | } | 
 | 6162 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6163 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDevice( | 
 | 6164 |                                                         audio_devices_t type, String8 address) const | 
 | 6165 | { | 
 | 6166 |     sp<DeviceDescriptor> device; | 
 | 6167 |     for (size_t i = 0; i < size(); i++) { | 
 | 6168 |         if (itemAt(i)->mDeviceType == type) { | 
 | 6169 |             device = itemAt(i); | 
 | 6170 |             if (itemAt(i)->mAddress = address) { | 
 | 6171 |                 break; | 
 | 6172 |             } | 
 | 6173 |         } | 
 | 6174 |     } | 
 | 6175 |     ALOGV("DeviceVector::getDevice() for type %d address %s found %p", | 
 | 6176 |           type, address.string(), device.get()); | 
 | 6177 |     return device; | 
 | 6178 | } | 
 | 6179 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6180 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromId( | 
 | 6181 |                                                                     audio_port_handle_t id) const | 
 | 6182 | { | 
 | 6183 |     sp<DeviceDescriptor> device; | 
 | 6184 |     for (size_t i = 0; i < size(); i++) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 6185 |         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] | 6186 |         if (itemAt(i)->mId == id) { | 
 | 6187 |             device = itemAt(i); | 
 | 6188 |             break; | 
 | 6189 |         } | 
 | 6190 |     } | 
 | 6191 |     return device; | 
 | 6192 | } | 
 | 6193 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6194 | AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromType( | 
 | 6195 |                                                                         audio_devices_t type) const | 
 | 6196 | { | 
 | 6197 |     DeviceVector devices; | 
 | 6198 |     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) { | 
 | 6199 |         if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) { | 
 | 6200 |             devices.add(itemAt(i)); | 
 | 6201 |             type &= ~itemAt(i)->mDeviceType; | 
 | 6202 |             ALOGV("DeviceVector::getDevicesFromType() for type %x found %p", | 
 | 6203 |                   itemAt(i)->mDeviceType, itemAt(i).get()); | 
 | 6204 |         } | 
 | 6205 |     } | 
 | 6206 |     return devices; | 
 | 6207 | } | 
 | 6208 |  | 
| Jean-Michel Trivi | 0fb4775 | 2014-07-22 16:19:14 -0700 | [diff] [blame] | 6209 | AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromTypeAddr( | 
 | 6210 |         audio_devices_t type, String8 address) const | 
 | 6211 | { | 
 | 6212 |     DeviceVector devices; | 
 | 6213 |     //ALOGV("   looking for device=%x, addr=%s", type, address.string()); | 
 | 6214 |     for (size_t i = 0; i < size(); i++) { | 
 | 6215 |         //ALOGV("     at i=%d: device=%x, addr=%s", | 
 | 6216 |         //        i, itemAt(i)->mDeviceType, itemAt(i)->mAddress.string()); | 
 | 6217 |         if (itemAt(i)->mDeviceType == type) { | 
 | 6218 |             if (itemAt(i)->mAddress == address) { | 
 | 6219 |                 //ALOGV("      found matching address %s", address.string()); | 
 | 6220 |                 devices.add(itemAt(i)); | 
 | 6221 |             } | 
 | 6222 |         } | 
 | 6223 |     } | 
 | 6224 |     return devices; | 
 | 6225 | } | 
 | 6226 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6227 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromName( | 
 | 6228 |         const String8& name) const | 
 | 6229 | { | 
 | 6230 |     sp<DeviceDescriptor> device; | 
 | 6231 |     for (size_t i = 0; i < size(); i++) { | 
 | 6232 |         if (itemAt(i)->mName == name) { | 
 | 6233 |             device = itemAt(i); | 
 | 6234 |             break; | 
 | 6235 |         } | 
 | 6236 |     } | 
 | 6237 |     return device; | 
 | 6238 | } | 
 | 6239 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6240 | void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig( | 
 | 6241 |                                                     struct audio_port_config *dstConfig, | 
 | 6242 |                                                     const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6243 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6244 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK|AUDIO_PORT_CONFIG_GAIN; | 
 | 6245 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 6246 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6247 |     } | 
 | 6248 |  | 
 | 6249 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 6250 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6251 |     dstConfig->id = mId; | 
 | 6252 |     dstConfig->role = audio_is_output_device(mDeviceType) ? | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6253 |                         AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6254 |     dstConfig->type = AUDIO_PORT_TYPE_DEVICE; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6255 |     dstConfig->ext.device.type = mDeviceType; | 
 | 6256 |     dstConfig->ext.device.hw_module = mModule->mHandle; | 
 | 6257 |     strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6258 | } | 
 | 6259 |  | 
 | 6260 | void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const | 
 | 6261 | { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 6262 |     ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6263 |     AudioPort::toAudioPort(port); | 
 | 6264 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6265 |     toAudioPortConfig(&port->active_config); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6266 |     port->ext.device.type = mDeviceType; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 6267 |     port->ext.device.hw_module = mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6268 |     strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); | 
 | 6269 | } | 
 | 6270 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6271 | status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces, int index) const | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6272 | { | 
 | 6273 |     const size_t SIZE = 256; | 
 | 6274 |     char buffer[SIZE]; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6275 |     String8 result; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6276 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6277 |     snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1); | 
 | 6278 |     result.append(buffer); | 
 | 6279 |     if (mId != 0) { | 
 | 6280 |         snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId); | 
 | 6281 |         result.append(buffer); | 
 | 6282 |     } | 
 | 6283 |     snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "", | 
 | 6284 |                                               enumToString(sDeviceNameToEnumTable, | 
 | 6285 |                                                            ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6286 |                                                            mDeviceType)); | 
 | 6287 |     result.append(buffer); | 
 | 6288 |     if (mAddress.size() != 0) { | 
 | 6289 |         snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string()); | 
 | 6290 |         result.append(buffer); | 
 | 6291 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6292 |     write(fd, result.string(), result.size()); | 
 | 6293 |     AudioPort::dump(fd, spaces); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6294 |  | 
 | 6295 |     return NO_ERROR; | 
 | 6296 | } | 
 | 6297 |  | 
 | 6298 |  | 
 | 6299 | // --- audio_policy.conf file parsing | 
 | 6300 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6301 | audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6302 | { | 
 | 6303 |     uint32_t flag = 0; | 
 | 6304 |  | 
 | 6305 |     // it is OK to cast name to non const here as we are not going to use it after | 
 | 6306 |     // strtok() modifies it | 
 | 6307 |     char *flagName = strtok(name, "|"); | 
 | 6308 |     while (flagName != NULL) { | 
 | 6309 |         if (strlen(flagName) != 0) { | 
 | 6310 |             flag |= stringToEnum(sFlagNameToEnumTable, | 
 | 6311 |                                ARRAY_SIZE(sFlagNameToEnumTable), | 
 | 6312 |                                flagName); | 
 | 6313 |         } | 
 | 6314 |         flagName = strtok(NULL, "|"); | 
 | 6315 |     } | 
 | 6316 |     //force direct flag if offload flag is set: offloading implies a direct output stream | 
 | 6317 |     // and all common behaviors are driven by checking only the direct flag | 
 | 6318 |     // this should normally be set appropriately in the policy configuration file | 
 | 6319 |     if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
 | 6320 |         flag |= AUDIO_OUTPUT_FLAG_DIRECT; | 
 | 6321 |     } | 
 | 6322 |  | 
 | 6323 |     return (audio_output_flags_t)flag; | 
 | 6324 | } | 
 | 6325 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6326 | audio_devices_t AudioPolicyManager::parseDeviceNames(char *name) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6327 | { | 
 | 6328 |     uint32_t device = 0; | 
 | 6329 |  | 
 | 6330 |     char *devName = strtok(name, "|"); | 
 | 6331 |     while (devName != NULL) { | 
 | 6332 |         if (strlen(devName) != 0) { | 
 | 6333 |             device |= stringToEnum(sDeviceNameToEnumTable, | 
 | 6334 |                                  ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6335 |                                  devName); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6336 |          } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6337 |         devName = strtok(NULL, "|"); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6338 |      } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6339 |     return device; | 
 | 6340 | } | 
 | 6341 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6342 | void AudioPolicyManager::loadHwModule(cnode *root) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6343 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6344 |     status_t status = NAME_NOT_FOUND; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6345 |     cnode *node; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6346 |     sp<HwModule> module = new HwModule(root->name); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6347 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6348 |     node = config_find(root, DEVICES_TAG); | 
 | 6349 |     if (node != NULL) { | 
 | 6350 |         node = node->first_child; | 
 | 6351 |         while (node) { | 
 | 6352 |             ALOGV("loadHwModule() loading device %s", node->name); | 
 | 6353 |             status_t tmpStatus = module->loadDevice(node); | 
 | 6354 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 6355 |                 status = tmpStatus; | 
 | 6356 |             } | 
 | 6357 |             node = node->next; | 
 | 6358 |         } | 
 | 6359 |     } | 
 | 6360 |     node = config_find(root, OUTPUTS_TAG); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6361 |     if (node != NULL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6362 |         node = node->first_child; | 
 | 6363 |         while (node) { | 
 | 6364 |             ALOGV("loadHwModule() loading output %s", node->name); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6365 |             status_t tmpStatus = module->loadOutput(node); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6366 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 6367 |                 status = tmpStatus; | 
 | 6368 |             } | 
 | 6369 |             node = node->next; | 
 | 6370 |         } | 
 | 6371 |     } | 
 | 6372 |     node = config_find(root, INPUTS_TAG); | 
 | 6373 |     if (node != NULL) { | 
 | 6374 |         node = node->first_child; | 
 | 6375 |         while (node) { | 
 | 6376 |             ALOGV("loadHwModule() loading input %s", node->name); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6377 |             status_t tmpStatus = module->loadInput(node); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6378 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 6379 |                 status = tmpStatus; | 
 | 6380 |             } | 
 | 6381 |             node = node->next; | 
 | 6382 |         } | 
 | 6383 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6384 |     loadGlobalConfig(root, module); | 
 | 6385 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6386 |     if (status == NO_ERROR) { | 
 | 6387 |         mHwModules.add(module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6388 |     } | 
 | 6389 | } | 
 | 6390 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6391 | void AudioPolicyManager::loadHwModules(cnode *root) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6392 | { | 
 | 6393 |     cnode *node = config_find(root, AUDIO_HW_MODULE_TAG); | 
 | 6394 |     if (node == NULL) { | 
 | 6395 |         return; | 
 | 6396 |     } | 
 | 6397 |  | 
 | 6398 |     node = node->first_child; | 
 | 6399 |     while (node) { | 
 | 6400 |         ALOGV("loadHwModules() loading module %s", node->name); | 
 | 6401 |         loadHwModule(node); | 
 | 6402 |         node = node->next; | 
 | 6403 |     } | 
 | 6404 | } | 
 | 6405 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6406 | void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6407 | { | 
 | 6408 |     cnode *node = config_find(root, GLOBAL_CONFIG_TAG); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 6409 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6410 |     if (node == NULL) { | 
 | 6411 |         return; | 
 | 6412 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6413 |     DeviceVector declaredDevices; | 
 | 6414 |     if (module != NULL) { | 
 | 6415 |         declaredDevices = module->mDeclaredDevices; | 
 | 6416 |     } | 
 | 6417 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6418 |     node = node->first_child; | 
 | 6419 |     while (node) { | 
 | 6420 |         if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6421 |             mAvailableOutputDevices.loadDevicesFromName((char *)node->value, | 
 | 6422 |                                                         declaredDevices); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6423 |             ALOGV("loadGlobalConfig() Attached Output Devices %08x", | 
 | 6424 |                   mAvailableOutputDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6425 |         } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6426 |             audio_devices_t device = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6427 |                                               ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6428 |                                               (char *)node->value); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6429 |             if (device != AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6430 |                 mDefaultOutputDevice = new DeviceDescriptor(String8(""), device); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6431 |             } else { | 
 | 6432 |                 ALOGW("loadGlobalConfig() default device not specified"); | 
 | 6433 |             } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6434 |             ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6435 |         } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6436 |             mAvailableInputDevices.loadDevicesFromName((char *)node->value, | 
 | 6437 |                                                        declaredDevices); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6438 |             ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6439 |         } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { | 
 | 6440 |             mSpeakerDrcEnabled = stringToBool((char *)node->value); | 
 | 6441 |             ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 6442 |         } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) { | 
 | 6443 |             uint32_t major, minor; | 
 | 6444 |             sscanf((char *)node->value, "%u.%u", &major, &minor); | 
 | 6445 |             module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor); | 
 | 6446 |             ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u", | 
 | 6447 |                   module->mHalVersion, major, minor); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6448 |         } | 
 | 6449 |         node = node->next; | 
 | 6450 |     } | 
 | 6451 | } | 
 | 6452 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6453 | status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6454 | { | 
 | 6455 |     cnode *root; | 
 | 6456 |     char *data; | 
 | 6457 |  | 
 | 6458 |     data = (char *)load_file(path, NULL); | 
 | 6459 |     if (data == NULL) { | 
 | 6460 |         return -ENODEV; | 
 | 6461 |     } | 
 | 6462 |     root = config_node("", ""); | 
 | 6463 |     config_load(root, data); | 
 | 6464 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6465 |     loadHwModules(root); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6466 |     // legacy audio_policy.conf files have one global_configuration section | 
 | 6467 |     loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6468 |     config_free(root); | 
 | 6469 |     free(root); | 
 | 6470 |     free(data); | 
 | 6471 |  | 
 | 6472 |     ALOGI("loadAudioPolicyConfig() loaded %s\n", path); | 
 | 6473 |  | 
 | 6474 |     return NO_ERROR; | 
 | 6475 | } | 
 | 6476 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6477 | void AudioPolicyManager::defaultAudioPolicyConfig(void) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6478 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6479 |     sp<HwModule> module; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6480 |     sp<IOProfile> profile; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6481 |     sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""), | 
 | 6482 |                                                                    AUDIO_DEVICE_IN_BUILTIN_MIC); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6483 |     mAvailableOutputDevices.add(mDefaultOutputDevice); | 
 | 6484 |     mAvailableInputDevices.add(defaultInputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6485 |  | 
 | 6486 |     module = new HwModule("primary"); | 
 | 6487 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6488 |     profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE, module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6489 |     profile->mSamplingRates.add(44100); | 
 | 6490 |     profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); | 
 | 6491 |     profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6492 |     profile->mSupportedDevices.add(mDefaultOutputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6493 |     profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY; | 
 | 6494 |     module->mOutputProfiles.add(profile); | 
 | 6495 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6496 |     profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK, module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6497 |     profile->mSamplingRates.add(8000); | 
 | 6498 |     profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); | 
 | 6499 |     profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6500 |     profile->mSupportedDevices.add(defaultInputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6501 |     module->mInputProfiles.add(profile); | 
 | 6502 |  | 
 | 6503 |     mHwModules.add(module); | 
 | 6504 | } | 
 | 6505 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 6506 | audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr) | 
 | 6507 | { | 
 | 6508 |     // flags to stream type mapping | 
 | 6509 |     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { | 
 | 6510 |         return AUDIO_STREAM_ENFORCED_AUDIBLE; | 
 | 6511 |     } | 
 | 6512 |     if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) { | 
 | 6513 |         return AUDIO_STREAM_BLUETOOTH_SCO; | 
 | 6514 |     } | 
 | 6515 |  | 
 | 6516 |     // usage to stream type mapping | 
 | 6517 |     switch (attr->usage) { | 
 | 6518 |     case AUDIO_USAGE_MEDIA: | 
 | 6519 |     case AUDIO_USAGE_GAME: | 
 | 6520 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
 | 6521 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 6522 |         return AUDIO_STREAM_MUSIC; | 
 | 6523 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 6524 |         return AUDIO_STREAM_SYSTEM; | 
 | 6525 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 6526 |         return AUDIO_STREAM_VOICE_CALL; | 
 | 6527 |  | 
 | 6528 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 6529 |         return AUDIO_STREAM_DTMF; | 
 | 6530 |  | 
 | 6531 |     case AUDIO_USAGE_ALARM: | 
 | 6532 |         return AUDIO_STREAM_ALARM; | 
 | 6533 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 6534 |         return AUDIO_STREAM_RING; | 
 | 6535 |  | 
 | 6536 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 6537 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 6538 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 6539 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 6540 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 6541 |         return AUDIO_STREAM_NOTIFICATION; | 
 | 6542 |  | 
 | 6543 |     case AUDIO_USAGE_UNKNOWN: | 
 | 6544 |     default: | 
 | 6545 |         return AUDIO_STREAM_MUSIC; | 
 | 6546 |     } | 
 | 6547 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6548 | }; // namespace android |