| 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 | 
 | 33 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 34 | #include <inttypes.h> | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 35 | #include <math.h> | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 36 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 37 | #include <cutils/properties.h> | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 38 | #include <utils/Log.h> | 
 | 39 | #include <hardware/audio.h> | 
 | 40 | #include <hardware/audio_effect.h> | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 41 | #include <media/AudioParameter.h> | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 42 | #include "AudioPolicyManager.h" | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 43 | #include "audio_policy_conf.h" | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 44 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 45 | namespace android { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 46 |  | 
 | 47 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 48 | // Definitions for audio_policy.conf file parsing | 
 | 49 | // ---------------------------------------------------------------------------- | 
 | 50 |  | 
 | 51 | struct StringToEnum { | 
 | 52 |     const char *name; | 
 | 53 |     uint32_t value; | 
 | 54 | }; | 
 | 55 |  | 
 | 56 | #define STRING_TO_ENUM(string) { #string, string } | 
 | 57 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | 
 | 58 |  | 
 | 59 | const StringToEnum sDeviceNameToEnumTable[] = { | 
 | 60 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE), | 
 | 61 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER), | 
 | 62 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET), | 
 | 63 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE), | 
 | 64 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO), | 
 | 65 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET), | 
 | 66 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT), | 
 | 67 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO), | 
 | 68 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP), | 
 | 69 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES), | 
 | 70 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), | 
 | 71 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP), | 
 | 72 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 73 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 74 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET), | 
 | 75 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET), | 
 | 76 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY), | 
 | 77 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE), | 
 | 78 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB), | 
 | 79 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 80 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX), | 
 | 81 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE), | 
 | 82 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC), | 
 | 83 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF), | 
 | 84 |     STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 85 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), | 
 | 86 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), | 
 | 87 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO), | 
 | 88 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET), | 
 | 89 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 90 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 91 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 92 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 93 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC), | 
 | 94 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX), | 
 | 95 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET), | 
 | 96 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET), | 
 | 97 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY), | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 98 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE), | 
| Eric Laurent | 1b77623 | 2014-05-19 17:26:41 -0700 | [diff] [blame] | 99 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER), | 
 | 100 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER), | 
 | 101 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE), | 
 | 102 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF), | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 103 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP), | 
| Terry Heo | 7999a22 | 2014-06-27 15:23:36 +0900 | [diff] [blame] | 104 |     STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 105 | }; | 
 | 106 |  | 
 | 107 | const StringToEnum sFlagNameToEnumTable[] = { | 
 | 108 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT), | 
 | 109 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY), | 
 | 110 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST), | 
 | 111 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), | 
 | 112 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), | 
 | 113 |     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING), | 
 | 114 | }; | 
 | 115 |  | 
 | 116 | const StringToEnum sFormatNameToEnumTable[] = { | 
 | 117 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT), | 
 | 118 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT), | 
 | 119 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT), | 
 | 120 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT), | 
 | 121 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT), | 
 | 122 |     STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED), | 
 | 123 |     STRING_TO_ENUM(AUDIO_FORMAT_MP3), | 
 | 124 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC), | 
| aarti jadhav-gaikwad | 2829edc | 2014-06-18 15:25:26 +0530 | [diff] [blame] | 125 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_MAIN), | 
 | 126 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC), | 
 | 127 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_SSR), | 
 | 128 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LTP), | 
 | 129 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1), | 
 | 130 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_SCALABLE), | 
 | 131 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ERLC), | 
 | 132 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_LD), | 
 | 133 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2), | 
 | 134 |     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ELD), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 135 |     STRING_TO_ENUM(AUDIO_FORMAT_VORBIS), | 
| Eric Laurent | ab5cdba | 2014-06-09 17:22:27 -0700 | [diff] [blame] | 136 |     STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1), | 
 | 137 |     STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2), | 
 | 138 |     STRING_TO_ENUM(AUDIO_FORMAT_OPUS), | 
 | 139 |     STRING_TO_ENUM(AUDIO_FORMAT_AC3), | 
 | 140 |     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 141 | }; | 
 | 142 |  | 
 | 143 | const StringToEnum sOutChannelsNameToEnumTable[] = { | 
 | 144 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO), | 
 | 145 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO), | 
 | 146 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), | 
 | 147 |     STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1), | 
 | 148 | }; | 
 | 149 |  | 
 | 150 | const StringToEnum sInChannelsNameToEnumTable[] = { | 
 | 151 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO), | 
 | 152 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO), | 
 | 153 |     STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK), | 
 | 154 | }; | 
 | 155 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 156 | const StringToEnum sGainModeNameToEnumTable[] = { | 
 | 157 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT), | 
 | 158 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS), | 
 | 159 |     STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP), | 
 | 160 | }; | 
 | 161 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 162 |  | 
 | 163 | uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table, | 
 | 164 |                                               size_t size, | 
 | 165 |                                               const char *name) | 
 | 166 | { | 
 | 167 |     for (size_t i = 0; i < size; i++) { | 
 | 168 |         if (strcmp(table[i].name, name) == 0) { | 
 | 169 |             ALOGV("stringToEnum() found %s", table[i].name); | 
 | 170 |             return table[i].value; | 
 | 171 |         } | 
 | 172 |     } | 
 | 173 |     return 0; | 
 | 174 | } | 
 | 175 |  | 
 | 176 | const char *AudioPolicyManager::enumToString(const struct StringToEnum *table, | 
 | 177 |                                               size_t size, | 
 | 178 |                                               uint32_t value) | 
 | 179 | { | 
 | 180 |     for (size_t i = 0; i < size; i++) { | 
 | 181 |         if (table[i].value == value) { | 
 | 182 |             return table[i].name; | 
 | 183 |         } | 
 | 184 |     } | 
 | 185 |     return ""; | 
 | 186 | } | 
 | 187 |  | 
 | 188 | bool AudioPolicyManager::stringToBool(const char *value) | 
 | 189 | { | 
 | 190 |     return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0)); | 
 | 191 | } | 
 | 192 |  | 
 | 193 |  | 
 | 194 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 195 | // AudioPolicyInterface implementation | 
 | 196 | // ---------------------------------------------------------------------------- | 
 | 197 |  | 
 | 198 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 199 | status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 200 |                                                           audio_policy_dev_state_t state, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 201 |                                                   const char *device_address) | 
 | 202 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 203 |     String8 address = String8(device_address); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 204 |  | 
 | 205 |     ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address); | 
 | 206 |  | 
 | 207 |     // connect/disconnect only 1 device at a time | 
 | 208 |     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE; | 
 | 209 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 210 |     // handle output devices | 
 | 211 |     if (audio_is_output_device(device)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 212 |         SortedVector <audio_io_handle_t> outputs; | 
 | 213 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 214 |         sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 215 |         devDesc->mAddress = address; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 216 |         ssize_t index = mAvailableOutputDevices.indexOf(devDesc); | 
 | 217 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 218 |         // save a copy of the opened output descriptors before any output is opened or closed | 
 | 219 |         // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies() | 
 | 220 |         mPreviousOutputs = mOutputs; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 221 |         switch (state) | 
 | 222 |         { | 
 | 223 |         // handle output device connection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 224 |         case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 225 |             if (index >= 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 226 |                 ALOGW("setDeviceConnectionState() device already connected: %x", device); | 
 | 227 |                 return INVALID_OPERATION; | 
 | 228 |             } | 
 | 229 |             ALOGV("setDeviceConnectionState() connecting device %x", device); | 
 | 230 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 231 |             if (checkOutputsForDevice(device, state, outputs, address) != NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 232 |                 return INVALID_OPERATION; | 
 | 233 |             } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 234 |             // outputs should never be empty here | 
 | 235 |             ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" | 
 | 236 |                     "checkOutputsForDevice() returned no outputs but status OK"); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 237 |             ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs", | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 238 |                   outputs.size()); | 
 | 239 |             // register new device as available | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 240 |             index = mAvailableOutputDevices.add(devDesc); | 
 | 241 |             if (index >= 0) { | 
 | 242 |                 mAvailableOutputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 243 |                 sp<HwModule> module = getModuleForDevice(device); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 244 |                 ALOG_ASSERT(module != NULL, "setDeviceConnectionState():" | 
 | 245 |                         "could not find HW module for device %08x", device); | 
 | 246 |                 mAvailableOutputDevices[index]->mModule = module; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 247 |             } else { | 
 | 248 |                 return NO_MEMORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 249 |             } | 
 | 250 |  | 
 | 251 |             break; | 
 | 252 |         // handle output device disconnection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 253 |         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 254 |             if (index < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 255 |                 ALOGW("setDeviceConnectionState() device not connected: %x", device); | 
 | 256 |                 return INVALID_OPERATION; | 
 | 257 |             } | 
 | 258 |  | 
 | 259 |             ALOGV("setDeviceConnectionState() disconnecting device %x", device); | 
 | 260 |             // remove device from available output devices | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 261 |             mAvailableOutputDevices.remove(devDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 262 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 263 |             checkOutputsForDevice(device, state, outputs, address); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 264 |             // not currently handling multiple simultaneous submixes: ignoring remote submix | 
 | 265 |             //   case and address | 
 | 266 |             } break; | 
 | 267 |  | 
 | 268 |         default: | 
 | 269 |             ALOGE("setDeviceConnectionState() invalid state: %x", state); | 
 | 270 |             return BAD_VALUE; | 
 | 271 |         } | 
 | 272 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 273 |         // checkA2dpSuspend must run before checkOutputForAllStrategies so that A2DP | 
 | 274 |         // output is suspended before any tracks are moved to it | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 275 |         checkA2dpSuspend(); | 
 | 276 |         checkOutputForAllStrategies(); | 
 | 277 |         // outputs must be closed after checkOutputForAllStrategies() is executed | 
 | 278 |         if (!outputs.isEmpty()) { | 
 | 279 |             for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 280 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 281 |                 // close unused outputs after device disconnection or direct outputs that have been | 
 | 282 |                 // opened by checkOutputsForDevice() to query dynamic parameters | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 283 |                 if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 284 |                         (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && | 
 | 285 |                          (desc->mDirectOpenCount == 0))) { | 
 | 286 |                     closeOutput(outputs[i]); | 
 | 287 |                 } | 
 | 288 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 289 |             // check again after closing A2DP output to reset mA2dpSuspended if needed | 
 | 290 |             checkA2dpSuspend(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 291 |         } | 
 | 292 |  | 
 | 293 |         updateDevicesAndOutputs(); | 
 | 294 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 295 |             // do not force device change on duplicated output because if device is 0, it will | 
 | 296 |             // also force a device 0 for the two outputs it is duplicated to which may override | 
 | 297 |             // a valid device selection on those outputs. | 
 | 298 |             setOutputDevice(mOutputs.keyAt(i), | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 299 |                             getNewOutputDevice(mOutputs.keyAt(i), true /*fromCache*/), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 300 |                             !mOutputs.valueAt(i)->isDuplicated(), | 
 | 301 |                             0); | 
 | 302 |         } | 
 | 303 |  | 
| Eric Laurent | 72aa32f | 2014-05-30 18:51:48 -0700 | [diff] [blame] | 304 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | b71e58b | 2014-05-29 16:08:11 -0700 | [diff] [blame] | 305 |         return NO_ERROR; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 306 |     }  // end if is output device | 
 | 307 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 308 |     // handle input devices | 
 | 309 |     if (audio_is_input_device(device)) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 310 |         SortedVector <audio_io_handle_t> inputs; | 
 | 311 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 312 |         sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 313 |         devDesc->mAddress = address; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 314 |         ssize_t index = mAvailableInputDevices.indexOf(devDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 315 |         switch (state) | 
 | 316 |         { | 
 | 317 |         // handle input device connection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 318 |         case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 319 |             if (index >= 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 320 |                 ALOGW("setDeviceConnectionState() device already connected: %d", device); | 
 | 321 |                 return INVALID_OPERATION; | 
 | 322 |             } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 323 |             sp<HwModule> module = getModuleForDevice(device); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 324 |             if (module == NULL) { | 
 | 325 |                 ALOGW("setDeviceConnectionState(): could not find HW module for device %08x", | 
 | 326 |                       device); | 
 | 327 |                 return INVALID_OPERATION; | 
 | 328 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 329 |             if (checkInputsForDevice(device, state, inputs, address) != NO_ERROR) { | 
 | 330 |                 return INVALID_OPERATION; | 
 | 331 |             } | 
 | 332 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 333 |             index = mAvailableInputDevices.add(devDesc); | 
 | 334 |             if (index >= 0) { | 
 | 335 |                 mAvailableInputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 336 |                 mAvailableInputDevices[index]->mModule = module; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 337 |             } else { | 
 | 338 |                 return NO_MEMORY; | 
 | 339 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 340 |         } break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 341 |  | 
 | 342 |         // handle input device disconnection | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 343 |         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 344 |             if (index < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 345 |                 ALOGW("setDeviceConnectionState() device not connected: %d", device); | 
 | 346 |                 return INVALID_OPERATION; | 
 | 347 |             } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 348 |             checkInputsForDevice(device, state, inputs, address); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 349 |             mAvailableInputDevices.remove(devDesc); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 350 |         } break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 351 |  | 
 | 352 |         default: | 
 | 353 |             ALOGE("setDeviceConnectionState() invalid state: %x", state); | 
 | 354 |             return BAD_VALUE; | 
 | 355 |         } | 
 | 356 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 357 |         closeAllInputs(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 358 |  | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 359 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 360 |         return NO_ERROR; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 361 |     } // end if is input device | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 362 |  | 
 | 363 |     ALOGW("setDeviceConnectionState() invalid device: %x", device); | 
 | 364 |     return BAD_VALUE; | 
 | 365 | } | 
 | 366 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 367 | audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 368 |                                                   const char *device_address) | 
 | 369 | { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 370 |     audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 371 |     String8 address = String8(device_address); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 372 |     sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device); | 
 | 373 |     devDesc->mAddress = String8(device_address); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 374 |     ssize_t index; | 
 | 375 |     DeviceVector *deviceVector; | 
 | 376 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 377 |     if (audio_is_output_device(device)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 378 |         deviceVector = &mAvailableOutputDevices; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 379 |     } else if (audio_is_input_device(device)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 380 |         deviceVector = &mAvailableInputDevices; | 
 | 381 |     } else { | 
 | 382 |         ALOGW("getDeviceConnectionState() invalid device type %08x", device); | 
 | 383 |         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 384 |     } | 
 | 385 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 386 |     index = deviceVector->indexOf(devDesc); | 
 | 387 |     if (index >= 0) { | 
 | 388 |         return AUDIO_POLICY_DEVICE_STATE_AVAILABLE; | 
 | 389 |     } else { | 
 | 390 |         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; | 
 | 391 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 392 | } | 
 | 393 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 394 | void AudioPolicyManager::setPhoneState(audio_mode_t state) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 395 | { | 
 | 396 |     ALOGV("setPhoneState() state %d", state); | 
 | 397 |     audio_devices_t newDevice = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 398 |     if (state < 0 || state >= AUDIO_MODE_CNT) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 399 |         ALOGW("setPhoneState() invalid state %d", state); | 
 | 400 |         return; | 
 | 401 |     } | 
 | 402 |  | 
 | 403 |     if (state == mPhoneState ) { | 
 | 404 |         ALOGW("setPhoneState() setting same state %d", state); | 
 | 405 |         return; | 
 | 406 |     } | 
 | 407 |  | 
 | 408 |     // if leaving call state, handle special case of active streams | 
 | 409 |     // pertaining to sonification strategy see handleIncallSonification() | 
 | 410 |     if (isInCall()) { | 
 | 411 |         ALOGV("setPhoneState() in call state management: new state is %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 412 |         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 413 |             handleIncallSonification((audio_stream_type_t)stream, false, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 414 |         } | 
 | 415 |     } | 
 | 416 |  | 
 | 417 |     // store previous phone state for management of sonification strategy below | 
 | 418 |     int oldState = mPhoneState; | 
 | 419 |     mPhoneState = state; | 
 | 420 |     bool force = false; | 
 | 421 |  | 
 | 422 |     // are we entering or starting a call | 
 | 423 |     if (!isStateInCall(oldState) && isStateInCall(state)) { | 
 | 424 |         ALOGV("  Entering call in setPhoneState()"); | 
 | 425 |         // force routing command to audio hardware when starting a call | 
 | 426 |         // even if no device change is needed | 
 | 427 |         force = true; | 
 | 428 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 429 |             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = | 
 | 430 |                     sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]; | 
 | 431 |         } | 
 | 432 |     } else if (isStateInCall(oldState) && !isStateInCall(state)) { | 
 | 433 |         ALOGV("  Exiting call in setPhoneState()"); | 
 | 434 |         // force routing command to audio hardware when exiting a call | 
 | 435 |         // even if no device change is needed | 
 | 436 |         force = true; | 
 | 437 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 438 |             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] = | 
 | 439 |                     sVolumeProfiles[AUDIO_STREAM_DTMF][j]; | 
 | 440 |         } | 
 | 441 |     } else if (isStateInCall(state) && (state != oldState)) { | 
 | 442 |         ALOGV("  Switching between telephony and VoIP in setPhoneState()"); | 
 | 443 |         // force routing command to audio hardware when switching between telephony and VoIP | 
 | 444 |         // even if no device change is needed | 
 | 445 |         force = true; | 
 | 446 |     } | 
 | 447 |  | 
 | 448 |     // check for device and output changes triggered by new phone state | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 449 |     newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 450 |     checkA2dpSuspend(); | 
 | 451 |     checkOutputForAllStrategies(); | 
 | 452 |     updateDevicesAndOutputs(); | 
 | 453 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 454 |     sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 455 |  | 
 | 456 |     // force routing command to audio hardware when ending call | 
 | 457 |     // even if no device change is needed | 
 | 458 |     if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { | 
 | 459 |         newDevice = hwOutputDesc->device(); | 
 | 460 |     } | 
 | 461 |  | 
 | 462 |     int delayMs = 0; | 
 | 463 |     if (isStateInCall(state)) { | 
 | 464 |         nsecs_t sysTime = systemTime(); | 
 | 465 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 466 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 467 |             // mute media and sonification strategies and delay device switch by the largest | 
 | 468 |             // latency of any output where either strategy is active. | 
 | 469 |             // This avoid sending the ring tone or music tail into the earpiece or headset. | 
 | 470 |             if ((desc->isStrategyActive(STRATEGY_MEDIA, | 
 | 471 |                                      SONIFICATION_HEADSET_MUSIC_DELAY, | 
 | 472 |                                      sysTime) || | 
 | 473 |                     desc->isStrategyActive(STRATEGY_SONIFICATION, | 
 | 474 |                                          SONIFICATION_HEADSET_MUSIC_DELAY, | 
 | 475 |                                          sysTime)) && | 
 | 476 |                     (delayMs < (int)desc->mLatency*2)) { | 
 | 477 |                 delayMs = desc->mLatency*2; | 
 | 478 |             } | 
 | 479 |             setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); | 
 | 480 |             setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, | 
 | 481 |                 getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); | 
 | 482 |             setStrategyMute(STRATEGY_SONIFICATION, true, mOutputs.keyAt(i)); | 
 | 483 |             setStrategyMute(STRATEGY_SONIFICATION, false, mOutputs.keyAt(i), MUTE_TIME_MS, | 
 | 484 |                 getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/)); | 
 | 485 |         } | 
 | 486 |     } | 
 | 487 |  | 
 | 488 |     // change routing is necessary | 
 | 489 |     setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); | 
 | 490 |  | 
 | 491 |     // if entering in call state, handle special case of active streams | 
 | 492 |     // pertaining to sonification strategy see handleIncallSonification() | 
 | 493 |     if (isStateInCall(state)) { | 
 | 494 |         ALOGV("setPhoneState() in call state management: new state is %d", state); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 495 |         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 496 |             handleIncallSonification((audio_stream_type_t)stream, true, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 497 |         } | 
 | 498 |     } | 
 | 499 |  | 
 | 500 |     // 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] | 501 |     if (state == AUDIO_MODE_RINGTONE && | 
 | 502 |         isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 503 |         mLimitRingtoneVolume = true; | 
 | 504 |     } else { | 
 | 505 |         mLimitRingtoneVolume = false; | 
 | 506 |     } | 
 | 507 | } | 
 | 508 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 509 | void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 510 |                                          audio_policy_forced_cfg_t config) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 511 | { | 
 | 512 |     ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState); | 
 | 513 |  | 
 | 514 |     bool forceVolumeReeval = false; | 
 | 515 |     switch(usage) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 516 |     case AUDIO_POLICY_FORCE_FOR_COMMUNICATION: | 
 | 517 |         if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO && | 
 | 518 |             config != AUDIO_POLICY_FORCE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 519 |             ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config); | 
 | 520 |             return; | 
 | 521 |         } | 
 | 522 |         forceVolumeReeval = true; | 
 | 523 |         mForceUse[usage] = config; | 
 | 524 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 525 |     case AUDIO_POLICY_FORCE_FOR_MEDIA: | 
 | 526 |         if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP && | 
 | 527 |             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 528 |             config != AUDIO_POLICY_FORCE_ANALOG_DOCK && | 
 | 529 |             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE && | 
| Jungshik Jang | 0c94309 | 2014-07-08 22:11:24 +0900 | [diff] [blame] | 530 |             config != AUDIO_POLICY_FORCE_NO_BT_A2DP) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 531 |             ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config); | 
 | 532 |             return; | 
 | 533 |         } | 
 | 534 |         mForceUse[usage] = config; | 
 | 535 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 536 |     case AUDIO_POLICY_FORCE_FOR_RECORD: | 
 | 537 |         if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 538 |             config != AUDIO_POLICY_FORCE_NONE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 539 |             ALOGW("setForceUse() invalid config %d for FOR_RECORD", config); | 
 | 540 |             return; | 
 | 541 |         } | 
 | 542 |         mForceUse[usage] = config; | 
 | 543 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 544 |     case AUDIO_POLICY_FORCE_FOR_DOCK: | 
 | 545 |         if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK && | 
 | 546 |             config != AUDIO_POLICY_FORCE_BT_DESK_DOCK && | 
 | 547 |             config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY && | 
 | 548 |             config != AUDIO_POLICY_FORCE_ANALOG_DOCK && | 
 | 549 |             config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 550 |             ALOGW("setForceUse() invalid config %d for FOR_DOCK", config); | 
 | 551 |         } | 
 | 552 |         forceVolumeReeval = true; | 
 | 553 |         mForceUse[usage] = config; | 
 | 554 |         break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 555 |     case AUDIO_POLICY_FORCE_FOR_SYSTEM: | 
 | 556 |         if (config != AUDIO_POLICY_FORCE_NONE && | 
 | 557 |             config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 558 |             ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config); | 
 | 559 |         } | 
 | 560 |         forceVolumeReeval = true; | 
 | 561 |         mForceUse[usage] = config; | 
 | 562 |         break; | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 563 |     case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO: | 
 | 564 |         if (config != AUDIO_POLICY_FORCE_NONE && | 
 | 565 |             config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) { | 
 | 566 |             ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config); | 
 | 567 |         } | 
 | 568 |         mForceUse[usage] = config; | 
 | 569 |         break; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 570 |     default: | 
 | 571 |         ALOGW("setForceUse() invalid usage %d", usage); | 
 | 572 |         break; | 
 | 573 |     } | 
 | 574 |  | 
 | 575 |     // check for device and output changes triggered by new force usage | 
 | 576 |     checkA2dpSuspend(); | 
 | 577 |     checkOutputForAllStrategies(); | 
 | 578 |     updateDevicesAndOutputs(); | 
 | 579 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 580 |         audio_io_handle_t output = mOutputs.keyAt(i); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 581 |         audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 582 |         setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE)); | 
 | 583 |         if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) { | 
 | 584 |             applyStreamVolumes(output, newDevice, 0, true); | 
 | 585 |         } | 
 | 586 |     } | 
 | 587 |  | 
 | 588 |     audio_io_handle_t activeInput = getActiveInput(); | 
 | 589 |     if (activeInput != 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 590 |         setInputDevice(activeInput, getNewInputDevice(activeInput)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 591 |     } | 
 | 592 |  | 
 | 593 | } | 
 | 594 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 595 | 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] | 596 | { | 
 | 597 |     return mForceUse[usage]; | 
 | 598 | } | 
 | 599 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 600 | void AudioPolicyManager::setSystemProperty(const char* property, const char* value) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 601 | { | 
 | 602 |     ALOGV("setSystemProperty() property %s, value %s", property, value); | 
 | 603 | } | 
 | 604 |  | 
 | 605 | // Find a direct output profile compatible with the parameters passed, even if the input flags do | 
 | 606 | // not explicitly request a direct output | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 607 | sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getProfileForDirectOutput( | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 608 |                                                                audio_devices_t device, | 
 | 609 |                                                                uint32_t samplingRate, | 
 | 610 |                                                                audio_format_t format, | 
 | 611 |                                                                audio_channel_mask_t channelMask, | 
 | 612 |                                                                audio_output_flags_t flags) | 
 | 613 | { | 
 | 614 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 615 |         if (mHwModules[i]->mHandle == 0) { | 
 | 616 |             continue; | 
 | 617 |         } | 
 | 618 |         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 619 |             sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 620 |             bool found = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 621 |             if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { | 
 | 622 |                 if (profile->isCompatibleProfile(device, samplingRate, format, | 
 | 623 |                                            channelMask, | 
 | 624 |                                            AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 625 |                     found = true; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 626 |                 } | 
 | 627 |             } else { | 
 | 628 |                 if (profile->isCompatibleProfile(device, samplingRate, format, | 
 | 629 |                                            channelMask, | 
 | 630 |                                            AUDIO_OUTPUT_FLAG_DIRECT)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 631 |                     found = true; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 632 |                 } | 
 | 633 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 634 |             if (found && (mAvailableOutputDevices.types() & profile->mSupportedDevices.types())) { | 
 | 635 |                 return profile; | 
 | 636 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 637 |         } | 
 | 638 |     } | 
 | 639 |     return 0; | 
 | 640 | } | 
 | 641 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 642 | audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 643 |                                     uint32_t samplingRate, | 
 | 644 |                                     audio_format_t format, | 
 | 645 |                                     audio_channel_mask_t channelMask, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 646 |                                     audio_output_flags_t flags, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 647 |                                     const audio_offload_info_t *offloadInfo) | 
 | 648 | { | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 649 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 650 |     routing_strategy strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 651 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 652 |     ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x", | 
 | 653 |           device, stream, samplingRate, format, channelMask, flags); | 
 | 654 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 655 |     return getOutputForDevice(device, stream, samplingRate,format, channelMask, flags, | 
 | 656 |             offloadInfo); | 
 | 657 | } | 
 | 658 |  | 
 | 659 | audio_io_handle_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr, | 
 | 660 |                                     uint32_t samplingRate, | 
 | 661 |                                     audio_format_t format, | 
 | 662 |                                     audio_channel_mask_t channelMask, | 
 | 663 |                                     audio_output_flags_t flags, | 
 | 664 |                                     const audio_offload_info_t *offloadInfo) | 
 | 665 | { | 
 | 666 |     if (attr == NULL) { | 
 | 667 |         ALOGE("getOutputForAttr() called with NULL audio attributes"); | 
 | 668 |         return 0; | 
 | 669 |     } | 
 | 670 |     ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s", | 
 | 671 |             attr->usage, attr->content_type, attr->tags); | 
 | 672 |  | 
 | 673 |     // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go | 
 | 674 |     routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr); | 
 | 675 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 676 |     ALOGV("getOutputForAttr() device %d, samplingRate %d, format %x, channelMask %x, flags %x", | 
 | 677 |           device, samplingRate, format, channelMask, flags); | 
 | 678 |  | 
 | 679 |     audio_stream_type_t stream = streamTypefromAttributesInt(attr); | 
 | 680 |     return getOutputForDevice(device, stream, samplingRate, format, channelMask, flags, | 
 | 681 |                 offloadInfo); | 
 | 682 | } | 
 | 683 |  | 
 | 684 | audio_io_handle_t AudioPolicyManager::getOutputForDevice( | 
 | 685 |         audio_devices_t device, | 
 | 686 |         audio_stream_type_t stream, | 
 | 687 |         uint32_t samplingRate, | 
 | 688 |         audio_format_t format, | 
 | 689 |         audio_channel_mask_t channelMask, | 
 | 690 |         audio_output_flags_t flags, | 
 | 691 |         const audio_offload_info_t *offloadInfo) | 
 | 692 | { | 
 | 693 |     audio_io_handle_t output = 0; | 
 | 694 |     uint32_t latency = 0; | 
 | 695 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 696 | #ifdef AUDIO_POLICY_TEST | 
 | 697 |     if (mCurOutput != 0) { | 
 | 698 |         ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d", | 
 | 699 |                 mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput); | 
 | 700 |  | 
 | 701 |         if (mTestOutputs[mCurOutput] == 0) { | 
 | 702 |             ALOGV("getOutput() opening test output"); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 703 |             sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 704 |             outputDesc->mDevice = mTestDevice; | 
 | 705 |             outputDesc->mSamplingRate = mTestSamplingRate; | 
 | 706 |             outputDesc->mFormat = mTestFormat; | 
 | 707 |             outputDesc->mChannelMask = mTestChannels; | 
 | 708 |             outputDesc->mLatency = mTestLatencyMs; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 709 |             outputDesc->mFlags = | 
 | 710 |                     (audio_output_flags_t)(mDirectOutput ? AUDIO_OUTPUT_FLAG_DIRECT : 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 711 |             outputDesc->mRefCount[stream] = 0; | 
 | 712 |             mTestOutputs[mCurOutput] = mpClientInterface->openOutput(0, &outputDesc->mDevice, | 
 | 713 |                                             &outputDesc->mSamplingRate, | 
 | 714 |                                             &outputDesc->mFormat, | 
 | 715 |                                             &outputDesc->mChannelMask, | 
 | 716 |                                             &outputDesc->mLatency, | 
 | 717 |                                             outputDesc->mFlags, | 
 | 718 |                                             offloadInfo); | 
 | 719 |             if (mTestOutputs[mCurOutput]) { | 
 | 720 |                 AudioParameter outputCmd = AudioParameter(); | 
 | 721 |                 outputCmd.addInt(String8("set_id"),mCurOutput); | 
 | 722 |                 mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString()); | 
 | 723 |                 addOutput(mTestOutputs[mCurOutput], outputDesc); | 
 | 724 |             } | 
 | 725 |         } | 
 | 726 |         return mTestOutputs[mCurOutput]; | 
 | 727 |     } | 
 | 728 | #endif //AUDIO_POLICY_TEST | 
 | 729 |  | 
 | 730 |     // open a direct output if required by specified parameters | 
 | 731 |     //force direct flag if offload flag is set: offloading implies a direct output stream | 
 | 732 |     // and all common behaviors are driven by checking only the direct flag | 
 | 733 |     // this should normally be set appropriately in the policy configuration file | 
 | 734 |     if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 735 |         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 736 |     } | 
 | 737 |  | 
 | 738 |     // Do not allow offloading if one non offloadable effect is enabled. This prevents from | 
 | 739 |     // creating an offloaded track and tearing it down immediately after start when audioflinger | 
 | 740 |     // detects there is an active non offloadable effect. | 
 | 741 |     // FIXME: We should check the audio session here but we do not have it in this context. | 
 | 742 |     // This may prevent offloading in rare situations where effects are left active by apps | 
 | 743 |     // in the background. | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 744 |     sp<IOProfile> profile; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 745 |     if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || | 
 | 746 |             !isNonOffloadableEffectEnabled()) { | 
 | 747 |         profile = getProfileForDirectOutput(device, | 
 | 748 |                                            samplingRate, | 
 | 749 |                                            format, | 
 | 750 |                                            channelMask, | 
 | 751 |                                            (audio_output_flags_t)flags); | 
 | 752 |     } | 
 | 753 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 754 |     if (profile != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 755 |         sp<AudioOutputDescriptor> outputDesc = NULL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 756 |  | 
 | 757 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 758 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 759 |             if (!desc->isDuplicated() && (profile == desc->mProfile)) { | 
 | 760 |                 outputDesc = desc; | 
 | 761 |                 // reuse direct output if currently open and configured with same parameters | 
 | 762 |                 if ((samplingRate == outputDesc->mSamplingRate) && | 
 | 763 |                         (format == outputDesc->mFormat) && | 
 | 764 |                         (channelMask == outputDesc->mChannelMask)) { | 
 | 765 |                     outputDesc->mDirectOpenCount++; | 
 | 766 |                     ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i)); | 
 | 767 |                     return mOutputs.keyAt(i); | 
 | 768 |                 } | 
 | 769 |             } | 
 | 770 |         } | 
 | 771 |         // close direct output if currently open and configured with different parameters | 
 | 772 |         if (outputDesc != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 773 |             closeOutput(outputDesc->mIoHandle); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 774 |         } | 
 | 775 |         outputDesc = new AudioOutputDescriptor(profile); | 
 | 776 |         outputDesc->mDevice = device; | 
 | 777 |         outputDesc->mSamplingRate = samplingRate; | 
 | 778 |         outputDesc->mFormat = format; | 
 | 779 |         outputDesc->mChannelMask = channelMask; | 
 | 780 |         outputDesc->mLatency = 0; | 
 | 781 |         outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); | 
 | 782 |         outputDesc->mRefCount[stream] = 0; | 
 | 783 |         outputDesc->mStopTime[stream] = 0; | 
 | 784 |         outputDesc->mDirectOpenCount = 1; | 
 | 785 |         output = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 786 |                                         &outputDesc->mDevice, | 
 | 787 |                                         &outputDesc->mSamplingRate, | 
 | 788 |                                         &outputDesc->mFormat, | 
 | 789 |                                         &outputDesc->mChannelMask, | 
 | 790 |                                         &outputDesc->mLatency, | 
 | 791 |                                         outputDesc->mFlags, | 
 | 792 |                                         offloadInfo); | 
 | 793 |  | 
 | 794 |         // only accept an output with the requested parameters | 
 | 795 |         if (output == 0 || | 
 | 796 |             (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) || | 
 | 797 |             (format != AUDIO_FORMAT_DEFAULT && format != outputDesc->mFormat) || | 
 | 798 |             (channelMask != 0 && channelMask != outputDesc->mChannelMask)) { | 
 | 799 |             ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d," | 
 | 800 |                     "format %d %d, channelMask %04x %04x", output, samplingRate, | 
 | 801 |                     outputDesc->mSamplingRate, format, outputDesc->mFormat, channelMask, | 
 | 802 |                     outputDesc->mChannelMask); | 
 | 803 |             if (output != 0) { | 
 | 804 |                 mpClientInterface->closeOutput(output); | 
 | 805 |             } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 806 |             return 0; | 
 | 807 |         } | 
 | 808 |         audio_io_handle_t srcOutput = getOutputForEffect(); | 
 | 809 |         addOutput(output, outputDesc); | 
 | 810 |         audio_io_handle_t dstOutput = getOutputForEffect(); | 
 | 811 |         if (dstOutput == output) { | 
 | 812 |             mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput); | 
 | 813 |         } | 
 | 814 |         mPreviousOutputs = mOutputs; | 
 | 815 |         ALOGV("getOutput() returns new direct output %d", output); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 816 |         mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 817 |         return output; | 
 | 818 |     } | 
 | 819 |  | 
 | 820 |     // ignoring channel mask due to downmix capability in mixer | 
 | 821 |  | 
 | 822 |     // open a non direct output | 
 | 823 |  | 
 | 824 |     // for non direct outputs, only PCM is supported | 
 | 825 |     if (audio_is_linear_pcm(format)) { | 
 | 826 |         // get which output is suitable for the specified stream. The actual | 
 | 827 |         // routing change will happen when startOutput() will be called | 
 | 828 |         SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); | 
 | 829 |  | 
 | 830 |         output = selectOutput(outputs, flags); | 
 | 831 |     } | 
 | 832 |     ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d," | 
 | 833 |             "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags); | 
 | 834 |  | 
 | 835 |     ALOGV("getOutput() returns output %d", output); | 
 | 836 |  | 
 | 837 |     return output; | 
 | 838 | } | 
 | 839 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 840 | 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] | 841 |                                                        audio_output_flags_t flags) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 842 | { | 
 | 843 |     // select one output among several that provide a path to a particular device or set of | 
 | 844 |     // devices (the list was previously build by getOutputsForDevice()). | 
 | 845 |     // The priority is as follows: | 
 | 846 |     // 1: the output with the highest number of requested policy flags | 
 | 847 |     // 2: the primary output | 
 | 848 |     // 3: the first output in the list | 
 | 849 |  | 
 | 850 |     if (outputs.size() == 0) { | 
 | 851 |         return 0; | 
 | 852 |     } | 
 | 853 |     if (outputs.size() == 1) { | 
 | 854 |         return outputs[0]; | 
 | 855 |     } | 
 | 856 |  | 
 | 857 |     int maxCommonFlags = 0; | 
 | 858 |     audio_io_handle_t outputFlags = 0; | 
 | 859 |     audio_io_handle_t outputPrimary = 0; | 
 | 860 |  | 
 | 861 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 862 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 863 |         if (!outputDesc->isDuplicated()) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 864 |             int commonFlags = popcount(outputDesc->mProfile->mFlags & flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 865 |             if (commonFlags > maxCommonFlags) { | 
 | 866 |                 outputFlags = outputs[i]; | 
 | 867 |                 maxCommonFlags = commonFlags; | 
 | 868 |                 ALOGV("selectOutput() commonFlags for output %d, %04x", outputs[i], commonFlags); | 
 | 869 |             } | 
 | 870 |             if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { | 
 | 871 |                 outputPrimary = outputs[i]; | 
 | 872 |             } | 
 | 873 |         } | 
 | 874 |     } | 
 | 875 |  | 
 | 876 |     if (outputFlags != 0) { | 
 | 877 |         return outputFlags; | 
 | 878 |     } | 
 | 879 |     if (outputPrimary != 0) { | 
 | 880 |         return outputPrimary; | 
 | 881 |     } | 
 | 882 |  | 
 | 883 |     return outputs[0]; | 
 | 884 | } | 
 | 885 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 886 | status_t AudioPolicyManager::startOutput(audio_io_handle_t output, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 887 |                                              audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 888 |                                              int session) | 
 | 889 | { | 
 | 890 |     ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session); | 
 | 891 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 892 |     if (index < 0) { | 
 | 893 |         ALOGW("startOutput() unknown output %d", output); | 
 | 894 |         return BAD_VALUE; | 
 | 895 |     } | 
 | 896 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 897 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 898 |  | 
 | 899 |     // increment usage count for this stream on the requested output: | 
 | 900 |     // NOTE that the usage count is the same for duplicated output and hardware output which is | 
 | 901 |     // necessary for a correct control of hardware output routing by startOutput() and stopOutput() | 
 | 902 |     outputDesc->changeRefCount(stream, 1); | 
 | 903 |  | 
 | 904 |     if (outputDesc->mRefCount[stream] == 1) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 905 |         audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 906 |         routing_strategy strategy = getStrategy(stream); | 
 | 907 |         bool shouldWait = (strategy == STRATEGY_SONIFICATION) || | 
 | 908 |                             (strategy == STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 909 |         uint32_t waitMs = 0; | 
 | 910 |         bool force = false; | 
 | 911 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 912 |             sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 913 |             if (desc != outputDesc) { | 
 | 914 |                 // force a device change if any other output is managed by the same hw | 
 | 915 |                 // module and has a current device selection that differs from selected device. | 
 | 916 |                 // In this case, the audio HAL must receive the new device selection so that it can | 
 | 917 |                 // change the device currently selected by the other active output. | 
 | 918 |                 if (outputDesc->sharesHwModuleWith(desc) && | 
 | 919 |                     desc->device() != newDevice) { | 
 | 920 |                     force = true; | 
 | 921 |                 } | 
 | 922 |                 // wait for audio on other active outputs to be presented when starting | 
 | 923 |                 // a notification so that audio focus effect can propagate. | 
 | 924 |                 uint32_t latency = desc->latency(); | 
 | 925 |                 if (shouldWait && desc->isActive(latency * 2) && (waitMs < latency)) { | 
 | 926 |                     waitMs = latency; | 
 | 927 |                 } | 
 | 928 |             } | 
 | 929 |         } | 
 | 930 |         uint32_t muteWaitMs = setOutputDevice(output, newDevice, force); | 
 | 931 |  | 
 | 932 |         // handle special case for sonification while in call | 
 | 933 |         if (isInCall()) { | 
 | 934 |             handleIncallSonification(stream, true, false); | 
 | 935 |         } | 
 | 936 |  | 
 | 937 |         // apply volume rules for current stream and device if necessary | 
 | 938 |         checkAndSetVolume(stream, | 
 | 939 |                           mStreams[stream].getVolumeIndex(newDevice), | 
 | 940 |                           output, | 
 | 941 |                           newDevice); | 
 | 942 |  | 
 | 943 |         // update the outputs if starting an output with a stream that can affect notification | 
 | 944 |         // routing | 
 | 945 |         handleNotificationRoutingForStream(stream); | 
 | 946 |         if (waitMs > muteWaitMs) { | 
 | 947 |             usleep((waitMs - muteWaitMs) * 2 * 1000); | 
 | 948 |         } | 
 | 949 |     } | 
 | 950 |     return NO_ERROR; | 
 | 951 | } | 
 | 952 |  | 
 | 953 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 954 | status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 955 |                                             audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 956 |                                             int session) | 
 | 957 | { | 
 | 958 |     ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session); | 
 | 959 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 960 |     if (index < 0) { | 
 | 961 |         ALOGW("stopOutput() unknown output %d", output); | 
 | 962 |         return BAD_VALUE; | 
 | 963 |     } | 
 | 964 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 965 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 966 |  | 
 | 967 |     // handle special case for sonification while in call | 
 | 968 |     if (isInCall()) { | 
 | 969 |         handleIncallSonification(stream, false, false); | 
 | 970 |     } | 
 | 971 |  | 
 | 972 |     if (outputDesc->mRefCount[stream] > 0) { | 
 | 973 |         // decrement usage count of this stream on the output | 
 | 974 |         outputDesc->changeRefCount(stream, -1); | 
 | 975 |         // store time at which the stream was stopped - see isStreamActive() | 
 | 976 |         if (outputDesc->mRefCount[stream] == 0) { | 
 | 977 |             outputDesc->mStopTime[stream] = systemTime(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 978 |             audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 979 |             // delay the device switch by twice the latency because stopOutput() is executed when | 
 | 980 |             // the track stop() command is received and at that time the audio track buffer can | 
 | 981 |             // still contain data that needs to be drained. The latency only covers the audio HAL | 
 | 982 |             // and kernel buffers. Also the latency does not always include additional delay in the | 
 | 983 |             // audio path (audio DSP, CODEC ...) | 
 | 984 |             setOutputDevice(output, newDevice, false, outputDesc->mLatency*2); | 
 | 985 |  | 
 | 986 |             // force restoring the device selection on other active outputs if it differs from the | 
 | 987 |             // one being selected for this output | 
 | 988 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 989 |                 audio_io_handle_t curOutput = mOutputs.keyAt(i); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 990 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 991 |                 if (curOutput != output && | 
 | 992 |                         desc->isActive() && | 
 | 993 |                         outputDesc->sharesHwModuleWith(desc) && | 
 | 994 |                         (newDevice != desc->device())) { | 
 | 995 |                     setOutputDevice(curOutput, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 996 |                                     getNewOutputDevice(curOutput, false /*fromCache*/), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 997 |                                     true, | 
 | 998 |                                     outputDesc->mLatency*2); | 
 | 999 |                 } | 
 | 1000 |             } | 
 | 1001 |             // update the outputs if stopping one with a stream that can affect notification routing | 
 | 1002 |             handleNotificationRoutingForStream(stream); | 
 | 1003 |         } | 
 | 1004 |         return NO_ERROR; | 
 | 1005 |     } else { | 
 | 1006 |         ALOGW("stopOutput() refcount is already 0 for output %d", output); | 
 | 1007 |         return INVALID_OPERATION; | 
 | 1008 |     } | 
 | 1009 | } | 
 | 1010 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1011 | void AudioPolicyManager::releaseOutput(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1012 | { | 
 | 1013 |     ALOGV("releaseOutput() %d", output); | 
 | 1014 |     ssize_t index = mOutputs.indexOfKey(output); | 
 | 1015 |     if (index < 0) { | 
 | 1016 |         ALOGW("releaseOutput() releasing unknown output %d", output); | 
 | 1017 |         return; | 
 | 1018 |     } | 
 | 1019 |  | 
 | 1020 | #ifdef AUDIO_POLICY_TEST | 
 | 1021 |     int testIndex = testOutputIndex(output); | 
 | 1022 |     if (testIndex != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1023 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1024 |         if (outputDesc->isActive()) { | 
 | 1025 |             mpClientInterface->closeOutput(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1026 |             mOutputs.removeItem(output); | 
 | 1027 |             mTestOutputs[testIndex] = 0; | 
 | 1028 |         } | 
 | 1029 |         return; | 
 | 1030 |     } | 
 | 1031 | #endif //AUDIO_POLICY_TEST | 
 | 1032 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1033 |     sp<AudioOutputDescriptor> desc = mOutputs.valueAt(index); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1034 |     if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1035 |         if (desc->mDirectOpenCount <= 0) { | 
 | 1036 |             ALOGW("releaseOutput() invalid open count %d for output %d", | 
 | 1037 |                                                               desc->mDirectOpenCount, output); | 
 | 1038 |             return; | 
 | 1039 |         } | 
 | 1040 |         if (--desc->mDirectOpenCount == 0) { | 
 | 1041 |             closeOutput(output); | 
 | 1042 |             // If effects where present on the output, audioflinger moved them to the primary | 
 | 1043 |             // output by default: move them back to the appropriate output. | 
 | 1044 |             audio_io_handle_t dstOutput = getOutputForEffect(); | 
 | 1045 |             if (dstOutput != mPrimaryOutput) { | 
 | 1046 |                 mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput); | 
 | 1047 |             } | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1048 |             mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1049 |         } | 
 | 1050 |     } | 
 | 1051 | } | 
 | 1052 |  | 
 | 1053 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1054 | audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1055 |                                     uint32_t samplingRate, | 
 | 1056 |                                     audio_format_t format, | 
 | 1057 |                                     audio_channel_mask_t channelMask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1058 |                                     audio_in_acoustics_t acoustics, | 
 | 1059 |                                     audio_input_flags_t flags) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1060 | { | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1061 |     ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x, " | 
 | 1062 |           "flags %#x", | 
 | 1063 |           inputSource, samplingRate, format, channelMask, acoustics, flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1064 |  | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1065 |     audio_devices_t device = getDeviceForInputSource(inputSource); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1066 |  | 
 | 1067 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 1068 |         ALOGW("getInput() could not find device for inputSource %d", inputSource); | 
 | 1069 |         return 0; | 
 | 1070 |     } | 
 | 1071 |  | 
 | 1072 |     // adapt channel selection to input source | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1073 |     switch (inputSource) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1074 |     case AUDIO_SOURCE_VOICE_UPLINK: | 
 | 1075 |         channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK; | 
 | 1076 |         break; | 
 | 1077 |     case AUDIO_SOURCE_VOICE_DOWNLINK: | 
 | 1078 |         channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK; | 
 | 1079 |         break; | 
 | 1080 |     case AUDIO_SOURCE_VOICE_CALL: | 
 | 1081 |         channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK; | 
 | 1082 |         break; | 
 | 1083 |     default: | 
 | 1084 |         break; | 
 | 1085 |     } | 
 | 1086 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1087 |     sp<IOProfile> profile = getInputProfile(device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1088 |                                          samplingRate, | 
 | 1089 |                                          format, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1090 |                                          channelMask, | 
 | 1091 |                                          flags); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1092 |     if (profile == 0) { | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1093 |         ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, " | 
 | 1094 |                 "channelMask 0x%X, flags %#x", | 
 | 1095 |                 device, samplingRate, format, channelMask, flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1096 |         return 0; | 
 | 1097 |     } | 
 | 1098 |  | 
 | 1099 |     if (profile->mModule->mHandle == 0) { | 
 | 1100 |         ALOGE("getInput(): HW module %s not opened", profile->mModule->mName); | 
 | 1101 |         return 0; | 
 | 1102 |     } | 
 | 1103 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1104 |     sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1105 |  | 
 | 1106 |     inputDesc->mInputSource = inputSource; | 
 | 1107 |     inputDesc->mDevice = device; | 
 | 1108 |     inputDesc->mSamplingRate = samplingRate; | 
 | 1109 |     inputDesc->mFormat = format; | 
 | 1110 |     inputDesc->mChannelMask = channelMask; | 
 | 1111 |     inputDesc->mRefCount = 0; | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1112 |     inputDesc->mOpenRefCount = 1; | 
 | 1113 |  | 
 | 1114 |     audio_io_handle_t input = mpClientInterface->openInput(profile->mModule->mHandle, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1115 |                                     &inputDesc->mDevice, | 
 | 1116 |                                     &inputDesc->mSamplingRate, | 
 | 1117 |                                     &inputDesc->mFormat, | 
| Glenn Kasten | ec40d28 | 2014-07-15 15:31:26 -0700 | [diff] [blame] | 1118 |                                     &inputDesc->mChannelMask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1119 |                                     flags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1120 |  | 
 | 1121 |     // only accept input with the exact requested set of parameters | 
 | 1122 |     if (input == 0 || | 
 | 1123 |         (samplingRate != inputDesc->mSamplingRate) || | 
 | 1124 |         (format != inputDesc->mFormat) || | 
 | 1125 |         (channelMask != inputDesc->mChannelMask)) { | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1126 |         ALOGW("getInput() failed opening input: samplingRate %d, format %d, channelMask %x", | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1127 |                 samplingRate, format, channelMask); | 
 | 1128 |         if (input != 0) { | 
 | 1129 |             mpClientInterface->closeInput(input); | 
 | 1130 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1131 |         return 0; | 
 | 1132 |     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1133 |     addInput(input, inputDesc); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1134 |     mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1135 |     return input; | 
 | 1136 | } | 
 | 1137 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1138 | status_t AudioPolicyManager::startInput(audio_io_handle_t input) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1139 | { | 
 | 1140 |     ALOGV("startInput() input %d", input); | 
 | 1141 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1142 |     if (index < 0) { | 
 | 1143 |         ALOGW("startInput() unknown input %d", input); | 
 | 1144 |         return BAD_VALUE; | 
 | 1145 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1146 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1147 |  | 
 | 1148 | #ifdef AUDIO_POLICY_TEST | 
 | 1149 |     if (mTestInput == 0) | 
 | 1150 | #endif //AUDIO_POLICY_TEST | 
 | 1151 |     { | 
 | 1152 |         // refuse 2 active AudioRecord clients at the same time except if the active input | 
 | 1153 |         // uses AUDIO_SOURCE_HOTWORD in which case it is closed. | 
 | 1154 |         audio_io_handle_t activeInput = getActiveInput(); | 
 | 1155 |         if (!isVirtualInputDevice(inputDesc->mDevice) && activeInput != 0) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1156 |             sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1157 |             if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) { | 
 | 1158 |                 ALOGW("startInput() preempting already started low-priority input %d", activeInput); | 
 | 1159 |                 stopInput(activeInput); | 
 | 1160 |                 releaseInput(activeInput); | 
 | 1161 |             } else { | 
 | 1162 |                 ALOGW("startInput() input %d failed: other input already started", input); | 
 | 1163 |                 return INVALID_OPERATION; | 
 | 1164 |             } | 
 | 1165 |         } | 
 | 1166 |     } | 
 | 1167 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1168 |     setInputDevice(input, getNewInputDevice(input), true /* force */); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1169 |  | 
 | 1170 |     // automatically enable the remote submix output when input is started | 
 | 1171 |     if (audio_is_remote_submix_device(inputDesc->mDevice)) { | 
 | 1172 |         setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1173 |                 AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1174 |     } | 
 | 1175 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1176 |     ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource); | 
 | 1177 |  | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1178 |     inputDesc->mRefCount++; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1179 |     return NO_ERROR; | 
 | 1180 | } | 
 | 1181 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1182 | status_t AudioPolicyManager::stopInput(audio_io_handle_t input) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1183 | { | 
 | 1184 |     ALOGV("stopInput() input %d", input); | 
 | 1185 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1186 |     if (index < 0) { | 
 | 1187 |         ALOGW("stopInput() unknown input %d", input); | 
 | 1188 |         return BAD_VALUE; | 
 | 1189 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1190 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1191 |  | 
 | 1192 |     if (inputDesc->mRefCount == 0) { | 
 | 1193 |         ALOGW("stopInput() input %d already stopped", input); | 
 | 1194 |         return INVALID_OPERATION; | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1195 |     } | 
 | 1196 |  | 
 | 1197 |     inputDesc->mRefCount--; | 
 | 1198 |     if (inputDesc->mRefCount == 0) { | 
 | 1199 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1200 |         // automatically disable the remote submix output when input is stopped | 
 | 1201 |         if (audio_is_remote_submix_device(inputDesc->mDevice)) { | 
 | 1202 |             setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1203 |                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1204 |         } | 
 | 1205 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1206 |         resetInputDevice(input); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1207 |     } | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1208 |     return NO_ERROR; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1209 | } | 
 | 1210 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1211 | void AudioPolicyManager::releaseInput(audio_io_handle_t input) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1212 | { | 
 | 1213 |     ALOGV("releaseInput() %d", input); | 
 | 1214 |     ssize_t index = mInputs.indexOfKey(input); | 
 | 1215 |     if (index < 0) { | 
 | 1216 |         ALOGW("releaseInput() releasing unknown input %d", input); | 
 | 1217 |         return; | 
 | 1218 |     } | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1219 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index); | 
 | 1220 |     ALOG_ASSERT(inputDesc != 0); | 
 | 1221 |     if (inputDesc->mOpenRefCount == 0) { | 
 | 1222 |         ALOGW("releaseInput() invalid open ref count %d", inputDesc->mOpenRefCount); | 
 | 1223 |         return; | 
 | 1224 |     } | 
 | 1225 |     inputDesc->mOpenRefCount--; | 
 | 1226 |     if (inputDesc->mOpenRefCount > 0) { | 
 | 1227 |         ALOGV("releaseInput() exit > 0"); | 
 | 1228 |         return; | 
 | 1229 |     } | 
 | 1230 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1231 |     mpClientInterface->closeInput(input); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1232 |     mInputs.removeItem(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1233 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 1234 |     mpClientInterface->onAudioPortListUpdate(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1235 |     ALOGV("releaseInput() exit"); | 
 | 1236 | } | 
 | 1237 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1238 | void AudioPolicyManager::closeAllInputs() { | 
 | 1239 |     for(size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 1240 |         mpClientInterface->closeInput(mInputs.keyAt(input_index)); | 
 | 1241 |     } | 
 | 1242 |     mInputs.clear(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1243 |     nextAudioPortGeneration(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1244 | } | 
 | 1245 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1246 | void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1247 |                                             int indexMin, | 
 | 1248 |                                             int indexMax) | 
 | 1249 | { | 
 | 1250 |     ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax); | 
 | 1251 |     if (indexMin < 0 || indexMin >= indexMax) { | 
 | 1252 |         ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax); | 
 | 1253 |         return; | 
 | 1254 |     } | 
 | 1255 |     mStreams[stream].mIndexMin = indexMin; | 
 | 1256 |     mStreams[stream].mIndexMax = indexMax; | 
 | 1257 | } | 
 | 1258 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1259 | status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1260 |                                                       int index, | 
 | 1261 |                                                       audio_devices_t device) | 
 | 1262 | { | 
 | 1263 |  | 
 | 1264 |     if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) { | 
 | 1265 |         return BAD_VALUE; | 
 | 1266 |     } | 
 | 1267 |     if (!audio_is_output_device(device)) { | 
 | 1268 |         return BAD_VALUE; | 
 | 1269 |     } | 
 | 1270 |  | 
 | 1271 |     // Force max volume if stream cannot be muted | 
 | 1272 |     if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax; | 
 | 1273 |  | 
 | 1274 |     ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d", | 
 | 1275 |           stream, device, index); | 
 | 1276 |  | 
 | 1277 |     // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and | 
 | 1278 |     // clear all device specific values | 
 | 1279 |     if (device == AUDIO_DEVICE_OUT_DEFAULT) { | 
 | 1280 |         mStreams[stream].mIndexCur.clear(); | 
 | 1281 |     } | 
 | 1282 |     mStreams[stream].mIndexCur.add(device, index); | 
 | 1283 |  | 
 | 1284 |     // compute and apply stream volume on all outputs according to connected device | 
 | 1285 |     status_t status = NO_ERROR; | 
 | 1286 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1287 |         audio_devices_t curDevice = | 
 | 1288 |                 getDeviceForVolume(mOutputs.valueAt(i)->device()); | 
 | 1289 |         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)) { | 
 | 1290 |             status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice); | 
 | 1291 |             if (volStatus != NO_ERROR) { | 
 | 1292 |                 status = volStatus; | 
 | 1293 |             } | 
 | 1294 |         } | 
 | 1295 |     } | 
 | 1296 |     return status; | 
 | 1297 | } | 
 | 1298 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1299 | status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1300 |                                                       int *index, | 
 | 1301 |                                                       audio_devices_t device) | 
 | 1302 | { | 
 | 1303 |     if (index == NULL) { | 
 | 1304 |         return BAD_VALUE; | 
 | 1305 |     } | 
 | 1306 |     if (!audio_is_output_device(device)) { | 
 | 1307 |         return BAD_VALUE; | 
 | 1308 |     } | 
 | 1309 |     // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to | 
 | 1310 |     // the strategy the stream belongs to. | 
 | 1311 |     if (device == AUDIO_DEVICE_OUT_DEFAULT) { | 
 | 1312 |         device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/); | 
 | 1313 |     } | 
 | 1314 |     device = getDeviceForVolume(device); | 
 | 1315 |  | 
 | 1316 |     *index =  mStreams[stream].getVolumeIndex(device); | 
 | 1317 |     ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index); | 
 | 1318 |     return NO_ERROR; | 
 | 1319 | } | 
 | 1320 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1321 | audio_io_handle_t AudioPolicyManager::selectOutputForEffects( | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1322 |                                             const SortedVector<audio_io_handle_t>& outputs) | 
 | 1323 | { | 
 | 1324 |     // select one output among several suitable for global effects. | 
 | 1325 |     // The priority is as follows: | 
 | 1326 |     // 1: An offloaded output. If the effect ends up not being offloadable, | 
 | 1327 |     //    AudioFlinger will invalidate the track and the offloaded output | 
 | 1328 |     //    will be closed causing the effect to be moved to a PCM output. | 
 | 1329 |     // 2: A deep buffer output | 
 | 1330 |     // 3: the first output in the list | 
 | 1331 |  | 
 | 1332 |     if (outputs.size() == 0) { | 
 | 1333 |         return 0; | 
 | 1334 |     } | 
 | 1335 |  | 
 | 1336 |     audio_io_handle_t outputOffloaded = 0; | 
 | 1337 |     audio_io_handle_t outputDeepBuffer = 0; | 
 | 1338 |  | 
 | 1339 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1340 |         sp<AudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1341 |         ALOGV("selectOutputForEffects outputs[%zu] flags %x", i, desc->mFlags); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1342 |         if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
 | 1343 |             outputOffloaded = outputs[i]; | 
 | 1344 |         } | 
 | 1345 |         if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) { | 
 | 1346 |             outputDeepBuffer = outputs[i]; | 
 | 1347 |         } | 
 | 1348 |     } | 
 | 1349 |  | 
 | 1350 |     ALOGV("selectOutputForEffects outputOffloaded %d outputDeepBuffer %d", | 
 | 1351 |           outputOffloaded, outputDeepBuffer); | 
 | 1352 |     if (outputOffloaded != 0) { | 
 | 1353 |         return outputOffloaded; | 
 | 1354 |     } | 
 | 1355 |     if (outputDeepBuffer != 0) { | 
 | 1356 |         return outputDeepBuffer; | 
 | 1357 |     } | 
 | 1358 |  | 
 | 1359 |     return outputs[0]; | 
 | 1360 | } | 
 | 1361 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1362 | audio_io_handle_t AudioPolicyManager::getOutputForEffect(const effect_descriptor_t *desc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1363 | { | 
 | 1364 |     // apply simple rule where global effects are attached to the same output as MUSIC streams | 
 | 1365 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1366 |     routing_strategy strategy = getStrategy(AUDIO_STREAM_MUSIC); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1367 |     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 1368 |     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(device, mOutputs); | 
 | 1369 |  | 
 | 1370 |     audio_io_handle_t output = selectOutputForEffects(dstOutputs); | 
 | 1371 |     ALOGV("getOutputForEffect() got output %d for fx %s flags %x", | 
 | 1372 |           output, (desc == NULL) ? "unspecified" : desc->name,  (desc == NULL) ? 0 : desc->flags); | 
 | 1373 |  | 
 | 1374 |     return output; | 
 | 1375 | } | 
 | 1376 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1377 | status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1378 |                                 audio_io_handle_t io, | 
 | 1379 |                                 uint32_t strategy, | 
 | 1380 |                                 int session, | 
 | 1381 |                                 int id) | 
 | 1382 | { | 
 | 1383 |     ssize_t index = mOutputs.indexOfKey(io); | 
 | 1384 |     if (index < 0) { | 
 | 1385 |         index = mInputs.indexOfKey(io); | 
 | 1386 |         if (index < 0) { | 
 | 1387 |             ALOGW("registerEffect() unknown io %d", io); | 
 | 1388 |             return INVALID_OPERATION; | 
 | 1389 |         } | 
 | 1390 |     } | 
 | 1391 |  | 
 | 1392 |     if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) { | 
 | 1393 |         ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB", | 
 | 1394 |                 desc->name, desc->memoryUsage); | 
 | 1395 |         return INVALID_OPERATION; | 
 | 1396 |     } | 
 | 1397 |     mTotalEffectsMemory += desc->memoryUsage; | 
 | 1398 |     ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d", | 
 | 1399 |             desc->name, io, strategy, session, id); | 
 | 1400 |     ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory); | 
 | 1401 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1402 |     sp<EffectDescriptor> effectDesc = new EffectDescriptor(); | 
 | 1403 |     memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t)); | 
 | 1404 |     effectDesc->mIo = io; | 
 | 1405 |     effectDesc->mStrategy = (routing_strategy)strategy; | 
 | 1406 |     effectDesc->mSession = session; | 
 | 1407 |     effectDesc->mEnabled = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1408 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1409 |     mEffects.add(id, effectDesc); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1410 |  | 
 | 1411 |     return NO_ERROR; | 
 | 1412 | } | 
 | 1413 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1414 | status_t AudioPolicyManager::unregisterEffect(int id) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1415 | { | 
 | 1416 |     ssize_t index = mEffects.indexOfKey(id); | 
 | 1417 |     if (index < 0) { | 
 | 1418 |         ALOGW("unregisterEffect() unknown effect ID %d", id); | 
 | 1419 |         return INVALID_OPERATION; | 
 | 1420 |     } | 
 | 1421 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1422 |     sp<EffectDescriptor> effectDesc = mEffects.valueAt(index); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1423 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1424 |     setEffectEnabled(effectDesc, false); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1425 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1426 |     if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1427 |         ALOGW("unregisterEffect() memory %d too big for total %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1428 |                 effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); | 
 | 1429 |         effectDesc->mDesc.memoryUsage = mTotalEffectsMemory; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1430 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1431 |     mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1432 |     ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1433 |             effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1434 |  | 
 | 1435 |     mEffects.removeItem(id); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1436 |  | 
 | 1437 |     return NO_ERROR; | 
 | 1438 | } | 
 | 1439 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1440 | status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1441 | { | 
 | 1442 |     ssize_t index = mEffects.indexOfKey(id); | 
 | 1443 |     if (index < 0) { | 
 | 1444 |         ALOGW("unregisterEffect() unknown effect ID %d", id); | 
 | 1445 |         return INVALID_OPERATION; | 
 | 1446 |     } | 
 | 1447 |  | 
 | 1448 |     return setEffectEnabled(mEffects.valueAt(index), enabled); | 
 | 1449 | } | 
 | 1450 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1451 | status_t AudioPolicyManager::setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1452 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1453 |     if (enabled == effectDesc->mEnabled) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1454 |         ALOGV("setEffectEnabled(%s) effect already %s", | 
 | 1455 |              enabled?"true":"false", enabled?"enabled":"disabled"); | 
 | 1456 |         return INVALID_OPERATION; | 
 | 1457 |     } | 
 | 1458 |  | 
 | 1459 |     if (enabled) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1460 |         if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1461 |             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] | 1462 |                  effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1463 |             return INVALID_OPERATION; | 
 | 1464 |         } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1465 |         mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1466 |         ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad); | 
 | 1467 |     } else { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1468 |         if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1469 |             ALOGW("setEffectEnabled(false) CPU load %d too high for total %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1470 |                     effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad); | 
 | 1471 |             effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1472 |         } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1473 |         mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1474 |         ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad); | 
 | 1475 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1476 |     effectDesc->mEnabled = enabled; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1477 |     return NO_ERROR; | 
 | 1478 | } | 
 | 1479 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1480 | bool AudioPolicyManager::isNonOffloadableEffectEnabled() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1481 | { | 
 | 1482 |     for (size_t i = 0; i < mEffects.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1483 |         sp<EffectDescriptor> effectDesc = mEffects.valueAt(i); | 
 | 1484 |         if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) && | 
 | 1485 |                 ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1486 |             ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d", | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1487 |                   effectDesc->mDesc.name, effectDesc->mSession); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1488 |             return true; | 
 | 1489 |         } | 
 | 1490 |     } | 
 | 1491 |     return false; | 
 | 1492 | } | 
 | 1493 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1494 | bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1495 | { | 
 | 1496 |     nsecs_t sysTime = systemTime(); | 
 | 1497 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1498 |         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1499 |         if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1500 |             return true; | 
 | 1501 |         } | 
 | 1502 |     } | 
 | 1503 |     return false; | 
 | 1504 | } | 
 | 1505 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1506 | bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1507 |                                                     uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1508 | { | 
 | 1509 |     nsecs_t sysTime = systemTime(); | 
 | 1510 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1511 |         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1512 |         if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1513 |                 outputDesc->isStreamActive(stream, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1514 |             return true; | 
 | 1515 |         } | 
 | 1516 |     } | 
 | 1517 |     return false; | 
 | 1518 | } | 
 | 1519 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1520 | bool AudioPolicyManager::isSourceActive(audio_source_t source) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1521 | { | 
 | 1522 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1523 |         const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1524 |         if ((inputDescriptor->mInputSource == (int)source || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1525 |                 (source == AUDIO_SOURCE_VOICE_RECOGNITION && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1526 |                  inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD)) | 
 | 1527 |              && (inputDescriptor->mRefCount > 0)) { | 
 | 1528 |             return true; | 
 | 1529 |         } | 
 | 1530 |     } | 
 | 1531 |     return false; | 
 | 1532 | } | 
 | 1533 |  | 
 | 1534 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1535 | status_t AudioPolicyManager::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1536 | { | 
 | 1537 |     const size_t SIZE = 256; | 
 | 1538 |     char buffer[SIZE]; | 
 | 1539 |     String8 result; | 
 | 1540 |  | 
 | 1541 |     snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this); | 
 | 1542 |     result.append(buffer); | 
 | 1543 |  | 
 | 1544 |     snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput); | 
 | 1545 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1546 |     snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState); | 
 | 1547 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1548 |     snprintf(buffer, SIZE, " Force use for communications %d\n", | 
 | 1549 |              mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1550 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1551 |     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] | 1552 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1553 |     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] | 1554 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1555 |     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] | 1556 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 1557 |     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] | 1558 |     result.append(buffer); | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 1559 |     snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n", | 
 | 1560 |             mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]); | 
 | 1561 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1562 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1563 |     snprintf(buffer, SIZE, " Available output devices:\n"); | 
 | 1564 |     result.append(buffer); | 
 | 1565 |     write(fd, result.string(), result.size()); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1566 |     for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1567 |         mAvailableOutputDevices[i]->dump(fd, 2, i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1568 |     } | 
 | 1569 |     snprintf(buffer, SIZE, "\n Available input devices:\n"); | 
 | 1570 |     write(fd, buffer, strlen(buffer)); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1571 |     for (size_t i = 0; i < mAvailableInputDevices.size(); i++) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1572 |         mAvailableInputDevices[i]->dump(fd, 2, i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 1573 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1574 |  | 
 | 1575 |     snprintf(buffer, SIZE, "\nHW Modules dump:\n"); | 
 | 1576 |     write(fd, buffer, strlen(buffer)); | 
 | 1577 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1578 |         snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1579 |         write(fd, buffer, strlen(buffer)); | 
 | 1580 |         mHwModules[i]->dump(fd); | 
 | 1581 |     } | 
 | 1582 |  | 
 | 1583 |     snprintf(buffer, SIZE, "\nOutputs dump:\n"); | 
 | 1584 |     write(fd, buffer, strlen(buffer)); | 
 | 1585 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1586 |         snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i)); | 
 | 1587 |         write(fd, buffer, strlen(buffer)); | 
 | 1588 |         mOutputs.valueAt(i)->dump(fd); | 
 | 1589 |     } | 
 | 1590 |  | 
 | 1591 |     snprintf(buffer, SIZE, "\nInputs dump:\n"); | 
 | 1592 |     write(fd, buffer, strlen(buffer)); | 
 | 1593 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 1594 |         snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i)); | 
 | 1595 |         write(fd, buffer, strlen(buffer)); | 
 | 1596 |         mInputs.valueAt(i)->dump(fd); | 
 | 1597 |     } | 
 | 1598 |  | 
 | 1599 |     snprintf(buffer, SIZE, "\nStreams dump:\n"); | 
 | 1600 |     write(fd, buffer, strlen(buffer)); | 
 | 1601 |     snprintf(buffer, SIZE, | 
 | 1602 |              " Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n"); | 
 | 1603 |     write(fd, buffer, strlen(buffer)); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 1604 |     for (size_t i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1605 |         snprintf(buffer, SIZE, " %02zu      ", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1606 |         write(fd, buffer, strlen(buffer)); | 
 | 1607 |         mStreams[i].dump(fd); | 
 | 1608 |     } | 
 | 1609 |  | 
 | 1610 |     snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n", | 
 | 1611 |             (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory); | 
 | 1612 |     write(fd, buffer, strlen(buffer)); | 
 | 1613 |  | 
 | 1614 |     snprintf(buffer, SIZE, "Registered effects:\n"); | 
 | 1615 |     write(fd, buffer, strlen(buffer)); | 
 | 1616 |     for (size_t i = 0; i < mEffects.size(); i++) { | 
 | 1617 |         snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i)); | 
 | 1618 |         write(fd, buffer, strlen(buffer)); | 
 | 1619 |         mEffects.valueAt(i)->dump(fd); | 
 | 1620 |     } | 
 | 1621 |  | 
 | 1622 |  | 
 | 1623 |     return NO_ERROR; | 
 | 1624 | } | 
 | 1625 |  | 
 | 1626 | // This function checks for the parameters which can be offloaded. | 
 | 1627 | // This can be enhanced depending on the capability of the DSP and policy | 
 | 1628 | // of the system. | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 1629 | bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadInfo) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1630 | { | 
 | 1631 |     ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d," | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 1632 |      " BitRate=%u, duration=%" PRId64 " us, has_video=%d", | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1633 |      offloadInfo.sample_rate, offloadInfo.channel_mask, | 
 | 1634 |      offloadInfo.format, | 
 | 1635 |      offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us, | 
 | 1636 |      offloadInfo.has_video); | 
 | 1637 |  | 
 | 1638 |     // Check if offload has been disabled | 
 | 1639 |     char propValue[PROPERTY_VALUE_MAX]; | 
 | 1640 |     if (property_get("audio.offload.disable", propValue, "0")) { | 
 | 1641 |         if (atoi(propValue) != 0) { | 
 | 1642 |             ALOGV("offload disabled by audio.offload.disable=%s", propValue ); | 
 | 1643 |             return false; | 
 | 1644 |         } | 
 | 1645 |     } | 
 | 1646 |  | 
 | 1647 |     // Check if stream type is music, then only allow offload as of now. | 
 | 1648 |     if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC) | 
 | 1649 |     { | 
 | 1650 |         ALOGV("isOffloadSupported: stream_type != MUSIC, returning false"); | 
 | 1651 |         return false; | 
 | 1652 |     } | 
 | 1653 |  | 
 | 1654 |     //TODO: enable audio offloading with video when ready | 
 | 1655 |     if (offloadInfo.has_video) | 
 | 1656 |     { | 
 | 1657 |         ALOGV("isOffloadSupported: has_video == true, returning false"); | 
 | 1658 |         return false; | 
 | 1659 |     } | 
 | 1660 |  | 
 | 1661 |     //If duration is less than minimum value defined in property, return false | 
 | 1662 |     if (property_get("audio.offload.min.duration.secs", propValue, NULL)) { | 
 | 1663 |         if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) { | 
 | 1664 |             ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue); | 
 | 1665 |             return false; | 
 | 1666 |         } | 
 | 1667 |     } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) { | 
 | 1668 |         ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS); | 
 | 1669 |         return false; | 
 | 1670 |     } | 
 | 1671 |  | 
 | 1672 |     // Do not allow offloading if one non offloadable effect is enabled. This prevents from | 
 | 1673 |     // creating an offloaded track and tearing it down immediately after start when audioflinger | 
 | 1674 |     // detects there is an active non offloadable effect. | 
 | 1675 |     // FIXME: We should check the audio session here but we do not have it in this context. | 
 | 1676 |     // This may prevent offloading in rare situations where effects are left active by apps | 
 | 1677 |     // in the background. | 
 | 1678 |     if (isNonOffloadableEffectEnabled()) { | 
 | 1679 |         return false; | 
 | 1680 |     } | 
 | 1681 |  | 
 | 1682 |     // See if there is a profile to support this. | 
 | 1683 |     // AUDIO_DEVICE_NONE | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1684 |     sp<IOProfile> profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1685 |                                             offloadInfo.sample_rate, | 
 | 1686 |                                             offloadInfo.format, | 
 | 1687 |                                             offloadInfo.channel_mask, | 
 | 1688 |                                             AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1689 |     ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT "); | 
 | 1690 |     return (profile != 0); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 1691 | } | 
 | 1692 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1693 | status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role, | 
 | 1694 |                                             audio_port_type_t type, | 
 | 1695 |                                             unsigned int *num_ports, | 
 | 1696 |                                             struct audio_port *ports, | 
 | 1697 |                                             unsigned int *generation) | 
 | 1698 | { | 
 | 1699 |     if (num_ports == NULL || (*num_ports != 0 && ports == NULL) || | 
 | 1700 |             generation == NULL) { | 
 | 1701 |         return BAD_VALUE; | 
 | 1702 |     } | 
 | 1703 |     ALOGV("listAudioPorts() role %d type %d num_ports %d ports %p", role, type, *num_ports, ports); | 
 | 1704 |     if (ports == NULL) { | 
 | 1705 |         *num_ports = 0; | 
 | 1706 |     } | 
 | 1707 |  | 
 | 1708 |     size_t portsWritten = 0; | 
 | 1709 |     size_t portsMax = *num_ports; | 
 | 1710 |     *num_ports = 0; | 
 | 1711 |     if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 1712 |         if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) { | 
 | 1713 |             for (size_t i = 0; | 
 | 1714 |                     i  < mAvailableOutputDevices.size() && portsWritten < portsMax; i++) { | 
 | 1715 |                 mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1716 |             } | 
 | 1717 |             *num_ports += mAvailableOutputDevices.size(); | 
 | 1718 |         } | 
 | 1719 |         if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) { | 
 | 1720 |             for (size_t i = 0; | 
 | 1721 |                     i  < mAvailableInputDevices.size() && portsWritten < portsMax; i++) { | 
 | 1722 |                 mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1723 |             } | 
 | 1724 |             *num_ports += mAvailableInputDevices.size(); | 
 | 1725 |         } | 
 | 1726 |     } | 
 | 1727 |     if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_MIX) { | 
 | 1728 |         if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) { | 
 | 1729 |             for (size_t i = 0; i < mInputs.size() && portsWritten < portsMax; i++) { | 
 | 1730 |                 mInputs[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1731 |             } | 
 | 1732 |             *num_ports += mInputs.size(); | 
 | 1733 |         } | 
 | 1734 |         if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1735 |             size_t numOutputs = 0; | 
 | 1736 |             for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1737 |                 if (!mOutputs[i]->isDuplicated()) { | 
 | 1738 |                     numOutputs++; | 
 | 1739 |                     if (portsWritten < portsMax) { | 
 | 1740 |                         mOutputs[i]->toAudioPort(&ports[portsWritten++]); | 
 | 1741 |                     } | 
 | 1742 |                 } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1743 |             } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1744 |             *num_ports += numOutputs; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1745 |         } | 
 | 1746 |     } | 
 | 1747 |     *generation = curAudioPortGeneration(); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 1748 |     ALOGV("listAudioPorts() got %zu ports needed %d", portsWritten, *num_ports); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1749 |     return NO_ERROR; | 
 | 1750 | } | 
 | 1751 |  | 
 | 1752 | status_t AudioPolicyManager::getAudioPort(struct audio_port *port __unused) | 
 | 1753 | { | 
 | 1754 |     return NO_ERROR; | 
 | 1755 | } | 
 | 1756 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1757 | sp<AudioPolicyManager::AudioOutputDescriptor> AudioPolicyManager::getOutputFromId( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1758 |                                                                     audio_port_handle_t id) const | 
 | 1759 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1760 |     sp<AudioOutputDescriptor> outputDesc = NULL; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1761 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 1762 |         outputDesc = mOutputs.valueAt(i); | 
 | 1763 |         if (outputDesc->mId == id) { | 
 | 1764 |             break; | 
 | 1765 |         } | 
 | 1766 |     } | 
 | 1767 |     return outputDesc; | 
 | 1768 | } | 
 | 1769 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1770 | sp<AudioPolicyManager::AudioInputDescriptor> AudioPolicyManager::getInputFromId( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1771 |                                                                     audio_port_handle_t id) const | 
 | 1772 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1773 |     sp<AudioInputDescriptor> inputDesc = NULL; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1774 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 1775 |         inputDesc = mInputs.valueAt(i); | 
 | 1776 |         if (inputDesc->mId == id) { | 
 | 1777 |             break; | 
 | 1778 |         } | 
 | 1779 |     } | 
 | 1780 |     return inputDesc; | 
 | 1781 | } | 
 | 1782 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1783 | sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleForDevice( | 
 | 1784 |                                                                     audio_devices_t device) const | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1785 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1786 |     sp <HwModule> module; | 
 | 1787 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1788 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 1789 |         if (mHwModules[i]->mHandle == 0) { | 
 | 1790 |             continue; | 
 | 1791 |         } | 
 | 1792 |         if (audio_is_output_device(device)) { | 
 | 1793 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 1794 |             { | 
 | 1795 |                 if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) { | 
 | 1796 |                     return mHwModules[i]; | 
 | 1797 |                 } | 
 | 1798 |             } | 
 | 1799 |         } else { | 
 | 1800 |             for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) { | 
 | 1801 |                 if (mHwModules[i]->mInputProfiles[j]->mSupportedDevices.types() & | 
 | 1802 |                         device & ~AUDIO_DEVICE_BIT_IN) { | 
 | 1803 |                     return mHwModules[i]; | 
 | 1804 |                 } | 
 | 1805 |             } | 
 | 1806 |         } | 
 | 1807 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1808 |     return module; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1809 | } | 
 | 1810 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1811 | sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleFromName(const char *name) const | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1812 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1813 |     sp <HwModule> module; | 
 | 1814 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1815 |     for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 1816 |     { | 
 | 1817 |         if (strcmp(mHwModules[i]->mName, name) == 0) { | 
 | 1818 |             return mHwModules[i]; | 
 | 1819 |         } | 
 | 1820 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1821 |     return module; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 1822 | } | 
 | 1823 |  | 
 | 1824 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1825 | status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, | 
 | 1826 |                                                audio_patch_handle_t *handle, | 
 | 1827 |                                                uid_t uid) | 
 | 1828 | { | 
 | 1829 |     ALOGV("createAudioPatch()"); | 
 | 1830 |  | 
 | 1831 |     if (handle == NULL || patch == NULL) { | 
 | 1832 |         return BAD_VALUE; | 
 | 1833 |     } | 
 | 1834 |     ALOGV("createAudioPatch() num sources %d num sinks %d", patch->num_sources, patch->num_sinks); | 
 | 1835 |  | 
 | 1836 |     if (patch->num_sources > 1 || patch->num_sinks > 1) { | 
 | 1837 |         return INVALID_OPERATION; | 
 | 1838 |     } | 
 | 1839 |     if (patch->sources[0].role != AUDIO_PORT_ROLE_SOURCE || | 
 | 1840 |             patch->sinks[0].role != AUDIO_PORT_ROLE_SINK) { | 
 | 1841 |         return INVALID_OPERATION; | 
 | 1842 |     } | 
 | 1843 |  | 
 | 1844 |     sp<AudioPatch> patchDesc; | 
 | 1845 |     ssize_t index = mAudioPatches.indexOfKey(*handle); | 
 | 1846 |  | 
 | 1847 |     ALOGV("createAudioPatch sink id %d role %d type %d", patch->sinks[0].id, patch->sinks[0].role, | 
 | 1848 |                                                          patch->sinks[0].type); | 
 | 1849 |     ALOGV("createAudioPatch source id %d role %d type %d", patch->sources[0].id, | 
 | 1850 |                                                            patch->sources[0].role, | 
 | 1851 |                                                            patch->sources[0].type); | 
 | 1852 |  | 
 | 1853 |     if (index >= 0) { | 
 | 1854 |         patchDesc = mAudioPatches.valueAt(index); | 
 | 1855 |         ALOGV("createAudioPatch() mUidCached %d patchDesc->mUid %d uid %d", | 
 | 1856 |                                                                   mUidCached, patchDesc->mUid, uid); | 
 | 1857 |         if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) { | 
 | 1858 |             return INVALID_OPERATION; | 
 | 1859 |         } | 
 | 1860 |     } else { | 
 | 1861 |         *handle = 0; | 
 | 1862 |     } | 
 | 1863 |  | 
 | 1864 |     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { | 
 | 1865 |         // TODO add support for mix to mix connection | 
 | 1866 |         if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { | 
 | 1867 |             ALOGV("createAudioPatch() source mix sink not device"); | 
 | 1868 |             return BAD_VALUE; | 
 | 1869 |         } | 
 | 1870 |         // output mix to output device connection | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1871 |         sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1872 |         if (outputDesc == NULL) { | 
 | 1873 |             ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id); | 
 | 1874 |             return BAD_VALUE; | 
 | 1875 |         } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1876 |         ALOG_ASSERT(!outputDesc->isDuplicated(),"duplicated output %d in source in ports", | 
 | 1877 |                                                 outputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1878 |         if (patchDesc != 0) { | 
 | 1879 |             if (patchDesc->mPatch.sources[0].id != patch->sources[0].id) { | 
 | 1880 |                 ALOGV("createAudioPatch() source id differs for patch current id %d new id %d", | 
 | 1881 |                                           patchDesc->mPatch.sources[0].id, patch->sources[0].id); | 
 | 1882 |                 return BAD_VALUE; | 
 | 1883 |             } | 
 | 1884 |         } | 
 | 1885 |         sp<DeviceDescriptor> devDesc = | 
 | 1886 |                 mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); | 
 | 1887 |         if (devDesc == 0) { | 
 | 1888 |             ALOGV("createAudioPatch() out device not found for id %d", patch->sinks[0].id); | 
 | 1889 |             return BAD_VALUE; | 
 | 1890 |         } | 
 | 1891 |  | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1892 |         if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1893 |                                                        patch->sources[0].sample_rate, | 
 | 1894 |                                                      patch->sources[0].format, | 
 | 1895 |                                                      patch->sources[0].channel_mask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1896 |                                                      AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1897 |             ALOGV("createAudioPatch() profile not supported"); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1898 |             return INVALID_OPERATION; | 
 | 1899 |         } | 
 | 1900 |         // TODO: reconfigure output format and channels here | 
 | 1901 |         ALOGV("createAudioPatch() setting device %08x on output %d", | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1902 |                                               devDesc->mDeviceType, outputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1903 |         setOutputDevice(outputDesc->mIoHandle, | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1904 |                         devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1905 |                        true, | 
 | 1906 |                        0, | 
 | 1907 |                        handle); | 
 | 1908 |         index = mAudioPatches.indexOfKey(*handle); | 
 | 1909 |         if (index >= 0) { | 
 | 1910 |             if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { | 
 | 1911 |                 ALOGW("createAudioPatch() setOutputDevice() did not reuse the patch provided"); | 
 | 1912 |             } | 
 | 1913 |             patchDesc = mAudioPatches.valueAt(index); | 
 | 1914 |             patchDesc->mUid = uid; | 
 | 1915 |             ALOGV("createAudioPatch() success"); | 
 | 1916 |         } else { | 
 | 1917 |             ALOGW("createAudioPatch() setOutputDevice() failed to create a patch"); | 
 | 1918 |             return INVALID_OPERATION; | 
 | 1919 |         } | 
 | 1920 |     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 1921 |         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { | 
 | 1922 |             // input device to input mix connection | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 1923 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1924 |             if (inputDesc == NULL) { | 
 | 1925 |                 return BAD_VALUE; | 
 | 1926 |             } | 
 | 1927 |             if (patchDesc != 0) { | 
 | 1928 |                 if (patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { | 
 | 1929 |                     return BAD_VALUE; | 
 | 1930 |                 } | 
 | 1931 |             } | 
 | 1932 |             sp<DeviceDescriptor> devDesc = | 
 | 1933 |                     mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); | 
 | 1934 |             if (devDesc == 0) { | 
 | 1935 |                 return BAD_VALUE; | 
 | 1936 |             } | 
 | 1937 |  | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1938 |             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1939 |                                                            patch->sinks[0].sample_rate, | 
 | 1940 |                                                          patch->sinks[0].format, | 
 | 1941 |                                                          patch->sinks[0].channel_mask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 1942 |                                                          // FIXME for the parameter type, | 
 | 1943 |                                                          // and the NONE | 
 | 1944 |                                                          (audio_output_flags_t) | 
 | 1945 |                                                             AUDIO_INPUT_FLAG_NONE)) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1946 |                 return INVALID_OPERATION; | 
 | 1947 |             } | 
 | 1948 |             // TODO: reconfigure output format and channels here | 
 | 1949 |             ALOGV("createAudioPatch() setting device %08x on output %d", | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1950 |                                                   devDesc->mDeviceType, inputDesc->mIoHandle); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1951 |             setInputDevice(inputDesc->mIoHandle, | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 1952 |                            devDesc->mDeviceType, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1953 |                            true, | 
 | 1954 |                            handle); | 
 | 1955 |             index = mAudioPatches.indexOfKey(*handle); | 
 | 1956 |             if (index >= 0) { | 
 | 1957 |                 if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) { | 
 | 1958 |                     ALOGW("createAudioPatch() setInputDevice() did not reuse the patch provided"); | 
 | 1959 |                 } | 
 | 1960 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 1961 |                 patchDesc->mUid = uid; | 
 | 1962 |                 ALOGV("createAudioPatch() success"); | 
 | 1963 |             } else { | 
 | 1964 |                 ALOGW("createAudioPatch() setInputDevice() failed to create a patch"); | 
 | 1965 |                 return INVALID_OPERATION; | 
 | 1966 |             } | 
 | 1967 |         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 1968 |             // device to device connection | 
 | 1969 |             if (patchDesc != 0) { | 
 | 1970 |                 if (patchDesc->mPatch.sources[0].id != patch->sources[0].id && | 
 | 1971 |                     patchDesc->mPatch.sinks[0].id != patch->sinks[0].id) { | 
 | 1972 |                     return BAD_VALUE; | 
 | 1973 |                 } | 
 | 1974 |             } | 
 | 1975 |  | 
 | 1976 |             sp<DeviceDescriptor> srcDeviceDesc = | 
 | 1977 |                     mAvailableInputDevices.getDeviceFromId(patch->sources[0].id); | 
 | 1978 |             sp<DeviceDescriptor> sinkDeviceDesc = | 
 | 1979 |                     mAvailableOutputDevices.getDeviceFromId(patch->sinks[0].id); | 
 | 1980 |             if (srcDeviceDesc == 0 || sinkDeviceDesc == 0) { | 
 | 1981 |                 return BAD_VALUE; | 
 | 1982 |             } | 
 | 1983 |             //update source and sink with our own data as the data passed in the patch may | 
 | 1984 |             // be incomplete. | 
 | 1985 |             struct audio_patch newPatch = *patch; | 
 | 1986 |             srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]); | 
 | 1987 |             sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[0], &patch->sinks[0]); | 
 | 1988 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 1989 |             if (srcDeviceDesc->mModule != sinkDeviceDesc->mModule) { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1990 |                 SortedVector<audio_io_handle_t> outputs = | 
 | 1991 |                                         getOutputsForDevice(sinkDeviceDesc->mDeviceType, mOutputs); | 
 | 1992 |                 // if the sink device is reachable via an opened output stream, request to go via | 
 | 1993 |                 // this output stream by adding a second source to the patch description | 
 | 1994 |                 audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE); | 
 | 1995 |                 if (output != AUDIO_IO_HANDLE_NONE) { | 
 | 1996 |                     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
 | 1997 |                     if (outputDesc->isDuplicated()) { | 
 | 1998 |                         return INVALID_OPERATION; | 
 | 1999 |                     } | 
 | 2000 |                     outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]); | 
 | 2001 |                     newPatch.num_sources = 2; | 
 | 2002 |                 } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2003 |             } | 
 | 2004 |             // TODO: check from routing capabilities in config file and other conflicting patches | 
 | 2005 |  | 
 | 2006 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 2007 |             if (index >= 0) { | 
 | 2008 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 2009 |             } | 
 | 2010 |  | 
 | 2011 |             status_t status = mpClientInterface->createAudioPatch(&newPatch, | 
 | 2012 |                                                                   &afPatchHandle, | 
 | 2013 |                                                                   0); | 
 | 2014 |             ALOGV("createAudioPatch() patch panel returned %d patchHandle %d", | 
 | 2015 |                                                                   status, afPatchHandle); | 
 | 2016 |             if (status == NO_ERROR) { | 
 | 2017 |                 if (index < 0) { | 
 | 2018 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 2019 |                                                &newPatch, uid); | 
 | 2020 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 2021 |                 } else { | 
 | 2022 |                     patchDesc->mPatch = newPatch; | 
 | 2023 |                 } | 
 | 2024 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 2025 |                 *handle = patchDesc->mHandle; | 
 | 2026 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 2027 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2028 |             } else { | 
 | 2029 |                 ALOGW("createAudioPatch() patch panel could not connect device patch, error %d", | 
 | 2030 |                 status); | 
 | 2031 |                 return INVALID_OPERATION; | 
 | 2032 |             } | 
 | 2033 |         } else { | 
 | 2034 |             return BAD_VALUE; | 
 | 2035 |         } | 
 | 2036 |     } else { | 
 | 2037 |         return BAD_VALUE; | 
 | 2038 |     } | 
 | 2039 |     return NO_ERROR; | 
 | 2040 | } | 
 | 2041 |  | 
 | 2042 | status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle, | 
 | 2043 |                                                   uid_t uid) | 
 | 2044 | { | 
 | 2045 |     ALOGV("releaseAudioPatch() patch %d", handle); | 
 | 2046 |  | 
 | 2047 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2048 |  | 
 | 2049 |     if (index < 0) { | 
 | 2050 |         return BAD_VALUE; | 
 | 2051 |     } | 
 | 2052 |     sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 2053 |     ALOGV("releaseAudioPatch() mUidCached %d patchDesc->mUid %d uid %d", | 
 | 2054 |           mUidCached, patchDesc->mUid, uid); | 
 | 2055 |     if (patchDesc->mUid != mUidCached && uid != patchDesc->mUid) { | 
 | 2056 |         return INVALID_OPERATION; | 
 | 2057 |     } | 
 | 2058 |  | 
 | 2059 |     struct audio_patch *patch = &patchDesc->mPatch; | 
 | 2060 |     patchDesc->mUid = mUidCached; | 
 | 2061 |     if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2062 |         sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2063 |         if (outputDesc == NULL) { | 
 | 2064 |             ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id); | 
 | 2065 |             return BAD_VALUE; | 
 | 2066 |         } | 
 | 2067 |  | 
 | 2068 |         setOutputDevice(outputDesc->mIoHandle, | 
 | 2069 |                         getNewOutputDevice(outputDesc->mIoHandle, true /*fromCache*/), | 
 | 2070 |                        true, | 
 | 2071 |                        0, | 
 | 2072 |                        NULL); | 
 | 2073 |     } else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2074 |         if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2075 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2076 |             if (inputDesc == NULL) { | 
 | 2077 |                 ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id); | 
 | 2078 |                 return BAD_VALUE; | 
 | 2079 |             } | 
 | 2080 |             setInputDevice(inputDesc->mIoHandle, | 
 | 2081 |                            getNewInputDevice(inputDesc->mIoHandle), | 
 | 2082 |                            true, | 
 | 2083 |                            NULL); | 
 | 2084 |         } else if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2085 |             audio_patch_handle_t afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 2086 |             status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
 | 2087 |             ALOGV("releaseAudioPatch() patch panel returned %d patchHandle %d", | 
 | 2088 |                                                               status, patchDesc->mAfPatchHandle); | 
 | 2089 |             removeAudioPatch(patchDesc->mHandle); | 
 | 2090 |             nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 2091 |             mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2092 |         } else { | 
 | 2093 |             return BAD_VALUE; | 
 | 2094 |         } | 
 | 2095 |     } else { | 
 | 2096 |         return BAD_VALUE; | 
 | 2097 |     } | 
 | 2098 |     return NO_ERROR; | 
 | 2099 | } | 
 | 2100 |  | 
 | 2101 | status_t AudioPolicyManager::listAudioPatches(unsigned int *num_patches, | 
 | 2102 |                                               struct audio_patch *patches, | 
 | 2103 |                                               unsigned int *generation) | 
 | 2104 | { | 
 | 2105 |     if (num_patches == NULL || (*num_patches != 0 && patches == NULL) || | 
 | 2106 |             generation == NULL) { | 
 | 2107 |         return BAD_VALUE; | 
 | 2108 |     } | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2109 |     ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2110 |           *num_patches, patches, mAudioPatches.size()); | 
 | 2111 |     if (patches == NULL) { | 
 | 2112 |         *num_patches = 0; | 
 | 2113 |     } | 
 | 2114 |  | 
 | 2115 |     size_t patchesWritten = 0; | 
 | 2116 |     size_t patchesMax = *num_patches; | 
 | 2117 |     for (size_t i = 0; | 
 | 2118 |             i  < mAudioPatches.size() && patchesWritten < patchesMax; i++) { | 
 | 2119 |         patches[patchesWritten] = mAudioPatches[i]->mPatch; | 
 | 2120 |         patches[patchesWritten++].id = mAudioPatches[i]->mHandle; | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2121 |         ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2122 |               i, mAudioPatches[i]->mPatch.num_sources, mAudioPatches[i]->mPatch.num_sinks); | 
 | 2123 |     } | 
 | 2124 |     *num_patches = mAudioPatches.size(); | 
 | 2125 |  | 
 | 2126 |     *generation = curAudioPortGeneration(); | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2127 |     ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2128 |     return NO_ERROR; | 
 | 2129 | } | 
 | 2130 |  | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2131 | status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config) | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2132 | { | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2133 |     ALOGV("setAudioPortConfig()"); | 
 | 2134 |  | 
 | 2135 |     if (config == NULL) { | 
 | 2136 |         return BAD_VALUE; | 
 | 2137 |     } | 
 | 2138 |     ALOGV("setAudioPortConfig() on port handle %d", config->id); | 
 | 2139 |     // Only support gain configuration for now | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2140 |     if (config->config_mask != AUDIO_PORT_CONFIG_GAIN) { | 
 | 2141 |         return INVALID_OPERATION; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2142 |     } | 
 | 2143 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2144 |     sp<AudioPortConfig> audioPortConfig; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2145 |     if (config->type == AUDIO_PORT_TYPE_MIX) { | 
 | 2146 |         if (config->role == AUDIO_PORT_ROLE_SOURCE) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2147 |             sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2148 |             if (outputDesc == NULL) { | 
 | 2149 |                 return BAD_VALUE; | 
 | 2150 |             } | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 2151 |             ALOG_ASSERT(!outputDesc->isDuplicated(), | 
 | 2152 |                         "setAudioPortConfig() called on duplicated output %d", | 
 | 2153 |                         outputDesc->mIoHandle); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2154 |             audioPortConfig = outputDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2155 |         } else if (config->role == AUDIO_PORT_ROLE_SINK) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2156 |             sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2157 |             if (inputDesc == NULL) { | 
 | 2158 |                 return BAD_VALUE; | 
 | 2159 |             } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2160 |             audioPortConfig = inputDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2161 |         } else { | 
 | 2162 |             return BAD_VALUE; | 
 | 2163 |         } | 
 | 2164 |     } else if (config->type == AUDIO_PORT_TYPE_DEVICE) { | 
 | 2165 |         sp<DeviceDescriptor> deviceDesc; | 
 | 2166 |         if (config->role == AUDIO_PORT_ROLE_SOURCE) { | 
 | 2167 |             deviceDesc = mAvailableInputDevices.getDeviceFromId(config->id); | 
 | 2168 |         } else if (config->role == AUDIO_PORT_ROLE_SINK) { | 
 | 2169 |             deviceDesc = mAvailableOutputDevices.getDeviceFromId(config->id); | 
 | 2170 |         } else { | 
 | 2171 |             return BAD_VALUE; | 
 | 2172 |         } | 
 | 2173 |         if (deviceDesc == NULL) { | 
 | 2174 |             return BAD_VALUE; | 
 | 2175 |         } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2176 |         audioPortConfig = deviceDesc; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2177 |     } else { | 
 | 2178 |         return BAD_VALUE; | 
 | 2179 |     } | 
 | 2180 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2181 |     struct audio_port_config backupConfig; | 
 | 2182 |     status_t status = audioPortConfig->applyAudioPortConfig(config, &backupConfig); | 
 | 2183 |     if (status == NO_ERROR) { | 
 | 2184 |         struct audio_port_config newConfig; | 
 | 2185 |         audioPortConfig->toAudioPortConfig(&newConfig, config); | 
 | 2186 |         status = mpClientInterface->setAudioPortConfig(&newConfig, 0); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2187 |     } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 2188 |     if (status != NO_ERROR) { | 
 | 2189 |         audioPortConfig->applyAudioPortConfig(&backupConfig); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2190 |     } | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 2191 |  | 
 | 2192 |     return status; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2193 | } | 
 | 2194 |  | 
 | 2195 | void AudioPolicyManager::clearAudioPatches(uid_t uid) | 
 | 2196 | { | 
 | 2197 |     for (ssize_t i = 0; i < (ssize_t)mAudioPatches.size(); i++)  { | 
 | 2198 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(i); | 
 | 2199 |         if (patchDesc->mUid == uid) { | 
 | 2200 |             // releaseAudioPatch() removes the patch from mAudioPatches | 
 | 2201 |             if (releaseAudioPatch(mAudioPatches.keyAt(i), uid) == NO_ERROR) { | 
 | 2202 |                 i--; | 
 | 2203 |             } | 
 | 2204 |         } | 
 | 2205 |     } | 
 | 2206 | } | 
 | 2207 |  | 
 | 2208 | status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle, | 
 | 2209 |                                            const sp<AudioPatch>& patch) | 
 | 2210 | { | 
 | 2211 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2212 |  | 
 | 2213 |     if (index >= 0) { | 
 | 2214 |         ALOGW("addAudioPatch() patch %d already in", handle); | 
 | 2215 |         return ALREADY_EXISTS; | 
 | 2216 |     } | 
 | 2217 |     mAudioPatches.add(handle, patch); | 
 | 2218 |     ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d" | 
 | 2219 |             "sink handle %d", | 
 | 2220 |           handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks, | 
 | 2221 |           patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id); | 
 | 2222 |     return NO_ERROR; | 
 | 2223 | } | 
 | 2224 |  | 
 | 2225 | status_t AudioPolicyManager::removeAudioPatch(audio_patch_handle_t handle) | 
 | 2226 | { | 
 | 2227 |     ssize_t index = mAudioPatches.indexOfKey(handle); | 
 | 2228 |  | 
 | 2229 |     if (index < 0) { | 
 | 2230 |         ALOGW("removeAudioPatch() patch %d not in", handle); | 
 | 2231 |         return ALREADY_EXISTS; | 
 | 2232 |     } | 
 | 2233 |     ALOGV("removeAudioPatch() handle %d af handle %d", handle, | 
 | 2234 |                       mAudioPatches.valueAt(index)->mAfPatchHandle); | 
 | 2235 |     mAudioPatches.removeItemsAt(index); | 
 | 2236 |     return NO_ERROR; | 
 | 2237 | } | 
 | 2238 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2239 | // ---------------------------------------------------------------------------- | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2240 | // AudioPolicyManager | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2241 | // ---------------------------------------------------------------------------- | 
 | 2242 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2243 | uint32_t AudioPolicyManager::nextUniqueId() | 
 | 2244 | { | 
 | 2245 |     return android_atomic_inc(&mNextUniqueId); | 
 | 2246 | } | 
 | 2247 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2248 | uint32_t AudioPolicyManager::nextAudioPortGeneration() | 
 | 2249 | { | 
 | 2250 |     return android_atomic_inc(&mAudioPortGeneration); | 
 | 2251 | } | 
 | 2252 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2253 | AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2254 |     : | 
 | 2255 | #ifdef AUDIO_POLICY_TEST | 
 | 2256 |     Thread(false), | 
 | 2257 | #endif //AUDIO_POLICY_TEST | 
 | 2258 |     mPrimaryOutput((audio_io_handle_t)0), | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2259 |     mPhoneState(AUDIO_MODE_NORMAL), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2260 |     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), | 
 | 2261 |     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2262 |     mA2dpSuspended(false), | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2263 |     mSpeakerDrcEnabled(false), mNextUniqueId(1), | 
 | 2264 |     mAudioPortGeneration(1) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2265 | { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2266 |     mUidCached = getuid(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2267 |     mpClientInterface = clientInterface; | 
 | 2268 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2269 |     for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) { | 
 | 2270 |         mForceUse[i] = AUDIO_POLICY_FORCE_NONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2271 |     } | 
 | 2272 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 2273 |     mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2274 |     if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) { | 
 | 2275 |         if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) { | 
 | 2276 |             ALOGE("could not load audio policy configuration file, setting defaults"); | 
 | 2277 |             defaultAudioPolicyConfig(); | 
 | 2278 |         } | 
 | 2279 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2280 |     // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2281 |  | 
 | 2282 |     // must be done after reading the policy | 
 | 2283 |     initializeVolumeCurves(); | 
 | 2284 |  | 
 | 2285 |     // open all output streams needed to access attached devices | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2286 |     audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types(); | 
 | 2287 |     audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2288 |     for (size_t i = 0; i < mHwModules.size(); i++) { | 
 | 2289 |         mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName); | 
 | 2290 |         if (mHwModules[i]->mHandle == 0) { | 
 | 2291 |             ALOGW("could not open HW module %s", mHwModules[i]->mName); | 
 | 2292 |             continue; | 
 | 2293 |         } | 
 | 2294 |         // open all output streams needed to access attached devices | 
 | 2295 |         // except for direct output streams that are only opened when they are actually | 
 | 2296 |         // required by an app. | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2297 |         // This also validates mAvailableOutputDevices list | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2298 |         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2299 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2300 |             const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2301 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2302 |             if (outProfile->mSupportedDevices.isEmpty()) { | 
 | 2303 |                 ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName); | 
 | 2304 |                 continue; | 
 | 2305 |             } | 
 | 2306 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2307 |             audio_devices_t profileType = outProfile->mSupportedDevices.types(); | 
 | 2308 |             if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) { | 
 | 2309 |                 profileType = mDefaultOutputDevice->mDeviceType; | 
 | 2310 |             } else { | 
 | 2311 |                 profileType = outProfile->mSupportedDevices[0]->mDeviceType; | 
 | 2312 |             } | 
 | 2313 |             if ((profileType & outputDeviceTypes) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2314 |                     ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2315 |                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(outProfile); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2316 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2317 |                 outputDesc->mDevice = profileType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2318 |                 audio_io_handle_t output = mpClientInterface->openOutput( | 
 | 2319 |                                                 outProfile->mModule->mHandle, | 
 | 2320 |                                                 &outputDesc->mDevice, | 
 | 2321 |                                                 &outputDesc->mSamplingRate, | 
 | 2322 |                                                 &outputDesc->mFormat, | 
 | 2323 |                                                 &outputDesc->mChannelMask, | 
 | 2324 |                                                 &outputDesc->mLatency, | 
 | 2325 |                                                 outputDesc->mFlags); | 
 | 2326 |                 if (output == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2327 |                     ALOGW("Cannot open output stream for device %08x on hw module %s", | 
 | 2328 |                           outputDesc->mDevice, | 
 | 2329 |                           mHwModules[i]->mName); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2330 |                 } else { | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2331 |                     for (size_t k = 0; k  < outProfile->mSupportedDevices.size(); k++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2332 |                         audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2333 |                         ssize_t index = | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2334 |                                 mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2335 |                         // give a valid ID to an attached device once confirmed it is reachable | 
 | 2336 |                         if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) { | 
 | 2337 |                             mAvailableOutputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2338 |                             mAvailableOutputDevices[index]->mModule = mHwModules[i]; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2339 |                         } | 
 | 2340 |                     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2341 |                     if (mPrimaryOutput == 0 && | 
 | 2342 |                             outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { | 
 | 2343 |                         mPrimaryOutput = output; | 
 | 2344 |                     } | 
 | 2345 |                     addOutput(output, outputDesc); | 
 | 2346 |                     setOutputDevice(output, | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2347 |                                     outputDesc->mDevice, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2348 |                                     true); | 
 | 2349 |                 } | 
 | 2350 |             } | 
 | 2351 |         } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2352 |         // open input streams needed to access attached devices to validate | 
 | 2353 |         // mAvailableInputDevices list | 
 | 2354 |         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) | 
 | 2355 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2356 |             const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2357 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2358 |             if (inProfile->mSupportedDevices.isEmpty()) { | 
 | 2359 |                 ALOGW("Input profile contains no device on module %s", mHwModules[i]->mName); | 
 | 2360 |                 continue; | 
 | 2361 |             } | 
 | 2362 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2363 |             audio_devices_t profileType = inProfile->mSupportedDevices[0]->mDeviceType; | 
 | 2364 |             if (profileType & inputDeviceTypes) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2365 |                 sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2366 |  | 
 | 2367 |                 inputDesc->mInputSource = AUDIO_SOURCE_MIC; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2368 |                 inputDesc->mDevice = profileType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2369 |                 audio_io_handle_t input = mpClientInterface->openInput( | 
 | 2370 |                                                     inProfile->mModule->mHandle, | 
 | 2371 |                                                     &inputDesc->mDevice, | 
 | 2372 |                                                     &inputDesc->mSamplingRate, | 
 | 2373 |                                                     &inputDesc->mFormat, | 
| Glenn Kasten | ec40d28 | 2014-07-15 15:31:26 -0700 | [diff] [blame] | 2374 |                                                     &inputDesc->mChannelMask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 2375 |                                                     AUDIO_INPUT_FLAG_NONE /*FIXME*/); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2376 |  | 
 | 2377 |                 if (input != 0) { | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2378 |                     for (size_t k = 0; k  < inProfile->mSupportedDevices.size(); k++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2379 |                         audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2380 |                         ssize_t index = | 
| Eric Laurent | 5b61ddd | 2014-05-07 09:10:01 -0700 | [diff] [blame] | 2381 |                                 mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2382 |                         // give a valid ID to an attached device once confirmed it is reachable | 
 | 2383 |                         if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) { | 
 | 2384 |                             mAvailableInputDevices[index]->mId = nextUniqueId(); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2385 |                             mAvailableInputDevices[index]->mModule = mHwModules[i]; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2386 |                         } | 
 | 2387 |                     } | 
 | 2388 |                     mpClientInterface->closeInput(input); | 
 | 2389 |                 } else { | 
 | 2390 |                     ALOGW("Cannot open input stream for device %08x on hw module %s", | 
 | 2391 |                           inputDesc->mDevice, | 
 | 2392 |                           mHwModules[i]->mName); | 
 | 2393 |                 } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2394 |             } | 
 | 2395 |         } | 
 | 2396 |     } | 
 | 2397 |     // make sure all attached devices have been allocated a unique ID | 
 | 2398 |     for (size_t i = 0; i  < mAvailableOutputDevices.size();) { | 
 | 2399 |         if (mAvailableOutputDevices[i]->mId == 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2400 |             ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2401 |             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]); | 
 | 2402 |             continue; | 
 | 2403 |         } | 
 | 2404 |         i++; | 
 | 2405 |     } | 
 | 2406 |     for (size_t i = 0; i  < mAvailableInputDevices.size();) { | 
 | 2407 |         if (mAvailableInputDevices[i]->mId == 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2408 |             ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2409 |             mAvailableInputDevices.remove(mAvailableInputDevices[i]); | 
 | 2410 |             continue; | 
 | 2411 |         } | 
 | 2412 |         i++; | 
 | 2413 |     } | 
 | 2414 |     // make sure default device is reachable | 
 | 2415 |     if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2416 |         ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2417 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2418 |  | 
 | 2419 |     ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output"); | 
 | 2420 |  | 
 | 2421 |     updateDevicesAndOutputs(); | 
 | 2422 |  | 
 | 2423 | #ifdef AUDIO_POLICY_TEST | 
 | 2424 |     if (mPrimaryOutput != 0) { | 
 | 2425 |         AudioParameter outputCmd = AudioParameter(); | 
 | 2426 |         outputCmd.addInt(String8("set_id"), 0); | 
 | 2427 |         mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); | 
 | 2428 |  | 
 | 2429 |         mTestDevice = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 2430 |         mTestSamplingRate = 44100; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2431 |         mTestFormat = AUDIO_FORMAT_PCM_16_BIT; | 
 | 2432 |         mTestChannels =  AUDIO_CHANNEL_OUT_STEREO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2433 |         mTestLatencyMs = 0; | 
 | 2434 |         mCurOutput = 0; | 
 | 2435 |         mDirectOutput = false; | 
 | 2436 |         for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { | 
 | 2437 |             mTestOutputs[i] = 0; | 
 | 2438 |         } | 
 | 2439 |  | 
 | 2440 |         const size_t SIZE = 256; | 
 | 2441 |         char buffer[SIZE]; | 
 | 2442 |         snprintf(buffer, SIZE, "AudioPolicyManagerTest"); | 
 | 2443 |         run(buffer, ANDROID_PRIORITY_AUDIO); | 
 | 2444 |     } | 
 | 2445 | #endif //AUDIO_POLICY_TEST | 
 | 2446 | } | 
 | 2447 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2448 | AudioPolicyManager::~AudioPolicyManager() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2449 | { | 
 | 2450 | #ifdef AUDIO_POLICY_TEST | 
 | 2451 |     exit(); | 
 | 2452 | #endif //AUDIO_POLICY_TEST | 
 | 2453 |    for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2454 |         mpClientInterface->closeOutput(mOutputs.keyAt(i)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2455 |    } | 
 | 2456 |    for (size_t i = 0; i < mInputs.size(); i++) { | 
 | 2457 |         mpClientInterface->closeInput(mInputs.keyAt(i)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2458 |    } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2459 |    mAvailableOutputDevices.clear(); | 
 | 2460 |    mAvailableInputDevices.clear(); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2461 |    mOutputs.clear(); | 
 | 2462 |    mInputs.clear(); | 
 | 2463 |    mHwModules.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2464 | } | 
 | 2465 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2466 | status_t AudioPolicyManager::initCheck() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2467 | { | 
 | 2468 |     return (mPrimaryOutput == 0) ? NO_INIT : NO_ERROR; | 
 | 2469 | } | 
 | 2470 |  | 
 | 2471 | #ifdef AUDIO_POLICY_TEST | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2472 | bool AudioPolicyManager::threadLoop() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2473 | { | 
 | 2474 |     ALOGV("entering threadLoop()"); | 
 | 2475 |     while (!exitPending()) | 
 | 2476 |     { | 
 | 2477 |         String8 command; | 
 | 2478 |         int valueInt; | 
 | 2479 |         String8 value; | 
 | 2480 |  | 
 | 2481 |         Mutex::Autolock _l(mLock); | 
 | 2482 |         mWaitWorkCV.waitRelative(mLock, milliseconds(50)); | 
 | 2483 |  | 
 | 2484 |         command = mpClientInterface->getParameters(0, String8("test_cmd_policy")); | 
 | 2485 |         AudioParameter param = AudioParameter(command); | 
 | 2486 |  | 
 | 2487 |         if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR && | 
 | 2488 |             valueInt != 0) { | 
 | 2489 |             ALOGV("Test command %s received", command.string()); | 
 | 2490 |             String8 target; | 
 | 2491 |             if (param.get(String8("target"), target) != NO_ERROR) { | 
 | 2492 |                 target = "Manager"; | 
 | 2493 |             } | 
 | 2494 |             if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) { | 
 | 2495 |                 param.remove(String8("test_cmd_policy_output")); | 
 | 2496 |                 mCurOutput = valueInt; | 
 | 2497 |             } | 
 | 2498 |             if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) { | 
 | 2499 |                 param.remove(String8("test_cmd_policy_direct")); | 
 | 2500 |                 if (value == "false") { | 
 | 2501 |                     mDirectOutput = false; | 
 | 2502 |                 } else if (value == "true") { | 
 | 2503 |                     mDirectOutput = true; | 
 | 2504 |                 } | 
 | 2505 |             } | 
 | 2506 |             if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) { | 
 | 2507 |                 param.remove(String8("test_cmd_policy_input")); | 
 | 2508 |                 mTestInput = valueInt; | 
 | 2509 |             } | 
 | 2510 |  | 
 | 2511 |             if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) { | 
 | 2512 |                 param.remove(String8("test_cmd_policy_format")); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2513 |                 int format = AUDIO_FORMAT_INVALID; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2514 |                 if (value == "PCM 16 bits") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2515 |                     format = AUDIO_FORMAT_PCM_16_BIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2516 |                 } else if (value == "PCM 8 bits") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2517 |                     format = AUDIO_FORMAT_PCM_8_BIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2518 |                 } else if (value == "Compressed MP3") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2519 |                     format = AUDIO_FORMAT_MP3; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2520 |                 } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2521 |                 if (format != AUDIO_FORMAT_INVALID) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2522 |                     if (target == "Manager") { | 
 | 2523 |                         mTestFormat = format; | 
 | 2524 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 2525 |                         AudioParameter outputParam = AudioParameter(); | 
 | 2526 |                         outputParam.addInt(String8("format"), format); | 
 | 2527 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 2528 |                     } | 
 | 2529 |                 } | 
 | 2530 |             } | 
 | 2531 |             if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) { | 
 | 2532 |                 param.remove(String8("test_cmd_policy_channels")); | 
 | 2533 |                 int channels = 0; | 
 | 2534 |  | 
 | 2535 |                 if (value == "Channels Stereo") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2536 |                     channels =  AUDIO_CHANNEL_OUT_STEREO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2537 |                 } else if (value == "Channels Mono") { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2538 |                     channels =  AUDIO_CHANNEL_OUT_MONO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2539 |                 } | 
 | 2540 |                 if (channels != 0) { | 
 | 2541 |                     if (target == "Manager") { | 
 | 2542 |                         mTestChannels = channels; | 
 | 2543 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 2544 |                         AudioParameter outputParam = AudioParameter(); | 
 | 2545 |                         outputParam.addInt(String8("channels"), channels); | 
 | 2546 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 2547 |                     } | 
 | 2548 |                 } | 
 | 2549 |             } | 
 | 2550 |             if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) { | 
 | 2551 |                 param.remove(String8("test_cmd_policy_sampleRate")); | 
 | 2552 |                 if (valueInt >= 0 && valueInt <= 96000) { | 
 | 2553 |                     int samplingRate = valueInt; | 
 | 2554 |                     if (target == "Manager") { | 
 | 2555 |                         mTestSamplingRate = samplingRate; | 
 | 2556 |                     } else if (mTestOutputs[mCurOutput] != 0) { | 
 | 2557 |                         AudioParameter outputParam = AudioParameter(); | 
 | 2558 |                         outputParam.addInt(String8("sampling_rate"), samplingRate); | 
 | 2559 |                         mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); | 
 | 2560 |                     } | 
 | 2561 |                 } | 
 | 2562 |             } | 
 | 2563 |  | 
 | 2564 |             if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) { | 
 | 2565 |                 param.remove(String8("test_cmd_policy_reopen")); | 
 | 2566 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2567 |                 sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2568 |                 mpClientInterface->closeOutput(mPrimaryOutput); | 
 | 2569 |  | 
 | 2570 |                 audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle; | 
 | 2571 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2572 |                 mOutputs.removeItem(mPrimaryOutput); | 
 | 2573 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2574 |                 sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2575 |                 outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 2576 |                 mPrimaryOutput = mpClientInterface->openOutput(moduleHandle, | 
 | 2577 |                                                 &outputDesc->mDevice, | 
 | 2578 |                                                 &outputDesc->mSamplingRate, | 
 | 2579 |                                                 &outputDesc->mFormat, | 
 | 2580 |                                                 &outputDesc->mChannelMask, | 
 | 2581 |                                                 &outputDesc->mLatency, | 
 | 2582 |                                                 outputDesc->mFlags); | 
 | 2583 |                 if (mPrimaryOutput == 0) { | 
 | 2584 |                     ALOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d", | 
 | 2585 |                             outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannelMask); | 
 | 2586 |                 } else { | 
 | 2587 |                     AudioParameter outputCmd = AudioParameter(); | 
 | 2588 |                     outputCmd.addInt(String8("set_id"), 0); | 
 | 2589 |                     mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString()); | 
 | 2590 |                     addOutput(mPrimaryOutput, outputDesc); | 
 | 2591 |                 } | 
 | 2592 |             } | 
 | 2593 |  | 
 | 2594 |  | 
 | 2595 |             mpClientInterface->setParameters(0, String8("test_cmd_policy=")); | 
 | 2596 |         } | 
 | 2597 |     } | 
 | 2598 |     return false; | 
 | 2599 | } | 
 | 2600 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2601 | void AudioPolicyManager::exit() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2602 | { | 
 | 2603 |     { | 
 | 2604 |         AutoMutex _l(mLock); | 
 | 2605 |         requestExit(); | 
 | 2606 |         mWaitWorkCV.signal(); | 
 | 2607 |     } | 
 | 2608 |     requestExitAndWait(); | 
 | 2609 | } | 
 | 2610 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2611 | int AudioPolicyManager::testOutputIndex(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2612 | { | 
 | 2613 |     for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { | 
 | 2614 |         if (output == mTestOutputs[i]) return i; | 
 | 2615 |     } | 
 | 2616 |     return 0; | 
 | 2617 | } | 
 | 2618 | #endif //AUDIO_POLICY_TEST | 
 | 2619 |  | 
 | 2620 | // --- | 
 | 2621 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2622 | void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2623 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2624 |     outputDesc->mIoHandle = output; | 
 | 2625 |     outputDesc->mId = nextUniqueId(); | 
 | 2626 |     mOutputs.add(output, outputDesc); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2627 |     nextAudioPortGeneration(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2628 | } | 
 | 2629 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2630 | void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc) | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2631 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2632 |     inputDesc->mIoHandle = input; | 
 | 2633 |     inputDesc->mId = nextUniqueId(); | 
 | 2634 |     mInputs.add(input, inputDesc); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2635 |     nextAudioPortGeneration(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2636 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2637 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2638 | String8 AudioPolicyManager::addressToParameter(audio_devices_t device, const String8 address) | 
 | 2639 | { | 
 | 2640 |     if (device & AUDIO_DEVICE_OUT_ALL_A2DP) { | 
 | 2641 |         return String8("a2dp_sink_address=")+address; | 
 | 2642 |     } | 
 | 2643 |     return address; | 
 | 2644 | } | 
 | 2645 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 2646 | status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2647 |                                                        audio_policy_dev_state_t state, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2648 |                                                        SortedVector<audio_io_handle_t>& outputs, | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2649 |                                                        const String8 address) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2650 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2651 |     sp<AudioOutputDescriptor> desc; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2652 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 2653 |     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2654 |         // first list already open outputs that can be routed to this device | 
 | 2655 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2656 |             desc = mOutputs.valueAt(i); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2657 |             if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2658 |                 ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i)); | 
 | 2659 |                 outputs.add(mOutputs.keyAt(i)); | 
 | 2660 |             } | 
 | 2661 |         } | 
 | 2662 |         // then look for output profiles that can be routed to this device | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2663 |         SortedVector< sp<IOProfile> > profiles; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2664 |         for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 2665 |         { | 
 | 2666 |             if (mHwModules[i]->mHandle == 0) { | 
 | 2667 |                 continue; | 
 | 2668 |             } | 
 | 2669 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2670 |             { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2671 |                 if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2672 |                     ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2673 |                     profiles.add(mHwModules[i]->mOutputProfiles[j]); | 
 | 2674 |                 } | 
 | 2675 |             } | 
 | 2676 |         } | 
 | 2677 |  | 
 | 2678 |         if (profiles.isEmpty() && outputs.isEmpty()) { | 
 | 2679 |             ALOGW("checkOutputsForDevice(): No output available for device %04x", device); | 
 | 2680 |             return BAD_VALUE; | 
 | 2681 |         } | 
 | 2682 |  | 
 | 2683 |         // open outputs for matching profiles if needed. Direct outputs are also opened to | 
 | 2684 |         // query for dynamic parameters and will be closed later by setDeviceConnectionState() | 
 | 2685 |         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] | 2686 |             sp<IOProfile> profile = profiles[profile_index]; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2687 |  | 
 | 2688 |             // nothing to do if one output is already opened for this profile | 
 | 2689 |             size_t j; | 
 | 2690 |             for (j = 0; j < mOutputs.size(); j++) { | 
 | 2691 |                 desc = mOutputs.valueAt(j); | 
 | 2692 |                 if (!desc->isDuplicated() && desc->mProfile == profile) { | 
 | 2693 |                     break; | 
 | 2694 |                 } | 
 | 2695 |             } | 
 | 2696 |             if (j != mOutputs.size()) { | 
 | 2697 |                 continue; | 
 | 2698 |             } | 
 | 2699 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 2700 |             ALOGV("opening output for device %08x with params %s profile %p", | 
 | 2701 |                                                       device, address.string(), profile.get()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2702 |             desc = new AudioOutputDescriptor(profile); | 
 | 2703 |             desc->mDevice = device; | 
 | 2704 |             audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; | 
 | 2705 |             offloadInfo.sample_rate = desc->mSamplingRate; | 
 | 2706 |             offloadInfo.format = desc->mFormat; | 
 | 2707 |             offloadInfo.channel_mask = desc->mChannelMask; | 
 | 2708 |  | 
 | 2709 |             audio_io_handle_t output = mpClientInterface->openOutput(profile->mModule->mHandle, | 
 | 2710 |                                                                        &desc->mDevice, | 
 | 2711 |                                                                        &desc->mSamplingRate, | 
 | 2712 |                                                                        &desc->mFormat, | 
 | 2713 |                                                                        &desc->mChannelMask, | 
 | 2714 |                                                                        &desc->mLatency, | 
 | 2715 |                                                                        desc->mFlags, | 
 | 2716 |                                                                        &offloadInfo); | 
 | 2717 |             if (output != 0) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2718 |                 // Here is where the out_set_parameters() for card & device gets called | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2719 |                 if (!address.isEmpty()) { | 
 | 2720 |                     mpClientInterface->setParameters(output, addressToParameter(device, address)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2721 |                 } | 
 | 2722 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2723 |                 // Here is where we step through and resolve any "dynamic" fields | 
 | 2724 |                 String8 reply; | 
 | 2725 |                 char *value; | 
 | 2726 |                 if (profile->mSamplingRates[0] == 0) { | 
 | 2727 |                     reply = mpClientInterface->getParameters(output, | 
 | 2728 |                                             String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); | 
 | 2729 |                     ALOGV("checkOutputsForDevice() direct output sup sampling rates %s", | 
 | 2730 |                               reply.string()); | 
 | 2731 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2732 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2733 |                         profile->loadSamplingRates(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2734 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2735 |                 } | 
 | 2736 |                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 2737 |                     reply = mpClientInterface->getParameters(output, | 
 | 2738 |                                                    String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); | 
 | 2739 |                     ALOGV("checkOutputsForDevice() direct output sup formats %s", | 
 | 2740 |                               reply.string()); | 
 | 2741 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2742 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2743 |                         profile->loadFormats(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2744 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2745 |                 } | 
 | 2746 |                 if (profile->mChannelMasks[0] == 0) { | 
 | 2747 |                     reply = mpClientInterface->getParameters(output, | 
 | 2748 |                                                   String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); | 
 | 2749 |                     ALOGV("checkOutputsForDevice() direct output sup channel masks %s", | 
 | 2750 |                               reply.string()); | 
 | 2751 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2752 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2753 |                         profile->loadOutChannels(value + 1); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2754 |                     } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2755 |                 } | 
 | 2756 |                 if (((profile->mSamplingRates[0] == 0) && | 
 | 2757 |                          (profile->mSamplingRates.size() < 2)) || | 
 | 2758 |                      ((profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) && | 
 | 2759 |                          (profile->mFormats.size() < 2)) || | 
 | 2760 |                      ((profile->mChannelMasks[0] == 0) && | 
 | 2761 |                          (profile->mChannelMasks.size() < 2))) { | 
 | 2762 |                     ALOGW("checkOutputsForDevice() direct output missing param"); | 
 | 2763 |                     mpClientInterface->closeOutput(output); | 
 | 2764 |                     output = 0; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 2765 |                 } else if (profile->mSamplingRates[0] == 0 || profile->mFormats[0] == 0 || | 
 | 2766 |                             profile->mChannelMasks[0] == 0) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2767 |                     mpClientInterface->closeOutput(output); | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 2768 |                     desc->mSamplingRate = profile->pickSamplingRate(); | 
 | 2769 |                     desc->mFormat = profile->pickFormat(); | 
 | 2770 |                     desc->mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2771 |                     offloadInfo.sample_rate = desc->mSamplingRate; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 2772 |                     offloadInfo.format = desc->mFormat; | 
 | 2773 |                     offloadInfo.channel_mask = desc->mChannelMask; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2774 |                     output = mpClientInterface->openOutput( | 
 | 2775 |                                                     profile->mModule->mHandle, | 
 | 2776 |                                                     &desc->mDevice, | 
 | 2777 |                                                     &desc->mSamplingRate, | 
 | 2778 |                                                     &desc->mFormat, | 
 | 2779 |                                                     &desc->mChannelMask, | 
 | 2780 |                                                     &desc->mLatency, | 
 | 2781 |                                                     desc->mFlags, | 
 | 2782 |                                                     &offloadInfo); | 
 | 2783 |                 } | 
 | 2784 |  | 
 | 2785 |                 if (output != 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2786 |                     addOutput(output, desc); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2787 |                     if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) { | 
 | 2788 |                         audio_io_handle_t duplicatedOutput = 0; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2789 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2790 |                         // set initial stream volume for device | 
 | 2791 |                         applyStreamVolumes(output, device, 0, true); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2792 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2793 |                         //TODO: configure audio effect output stage here | 
 | 2794 |  | 
 | 2795 |                         // open a duplicating output thread for the new output and the primary output | 
 | 2796 |                         duplicatedOutput = mpClientInterface->openDuplicateOutput(output, | 
 | 2797 |                                                                                   mPrimaryOutput); | 
 | 2798 |                         if (duplicatedOutput != 0) { | 
 | 2799 |                             // add duplicated output descriptor | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2800 |                             sp<AudioOutputDescriptor> dupOutputDesc = new AudioOutputDescriptor(NULL); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2801 |                             dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput); | 
 | 2802 |                             dupOutputDesc->mOutput2 = mOutputs.valueFor(output); | 
 | 2803 |                             dupOutputDesc->mSamplingRate = desc->mSamplingRate; | 
 | 2804 |                             dupOutputDesc->mFormat = desc->mFormat; | 
 | 2805 |                             dupOutputDesc->mChannelMask = desc->mChannelMask; | 
 | 2806 |                             dupOutputDesc->mLatency = desc->mLatency; | 
 | 2807 |                             addOutput(duplicatedOutput, dupOutputDesc); | 
 | 2808 |                             applyStreamVolumes(duplicatedOutput, device, 0, true); | 
 | 2809 |                         } else { | 
 | 2810 |                             ALOGW("checkOutputsForDevice() could not open dup output for %d and %d", | 
 | 2811 |                                     mPrimaryOutput, output); | 
 | 2812 |                             mpClientInterface->closeOutput(output); | 
 | 2813 |                             mOutputs.removeItem(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 2814 |                             nextAudioPortGeneration(); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2815 |                             output = 0; | 
 | 2816 |                         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2817 |                     } | 
 | 2818 |                 } | 
 | 2819 |             } | 
 | 2820 |             if (output == 0) { | 
 | 2821 |                 ALOGW("checkOutputsForDevice() could not open output for device %x", device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2822 |                 profiles.removeAt(profile_index); | 
 | 2823 |                 profile_index--; | 
 | 2824 |             } else { | 
 | 2825 |                 outputs.add(output); | 
 | 2826 |                 ALOGV("checkOutputsForDevice(): adding output %d", output); | 
 | 2827 |             } | 
 | 2828 |         } | 
 | 2829 |  | 
 | 2830 |         if (profiles.isEmpty()) { | 
 | 2831 |             ALOGW("checkOutputsForDevice(): No output available for device %04x", device); | 
 | 2832 |             return BAD_VALUE; | 
 | 2833 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2834 |     } else { // Disconnect | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2835 |         // check if one opened output is not needed any more after disconnecting one device | 
 | 2836 |         for (size_t i = 0; i < mOutputs.size(); i++) { | 
 | 2837 |             desc = mOutputs.valueAt(i); | 
 | 2838 |             if (!desc->isDuplicated() && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 2839 |                     !(desc->mProfile->mSupportedDevices.types() & | 
 | 2840 |                             mAvailableOutputDevices.types())) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2841 |                 ALOGV("checkOutputsForDevice(): disconnecting adding output %d", mOutputs.keyAt(i)); | 
 | 2842 |                 outputs.add(mOutputs.keyAt(i)); | 
 | 2843 |             } | 
 | 2844 |         } | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2845 |         // Clear any profiles associated with the disconnected device. | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2846 |         for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 2847 |         { | 
 | 2848 |             if (mHwModules[i]->mHandle == 0) { | 
 | 2849 |                 continue; | 
 | 2850 |             } | 
 | 2851 |             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) | 
 | 2852 |             { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2853 |                 sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2854 |                 if (profile->mSupportedDevices.types() & device) { | 
 | 2855 |                     ALOGV("checkOutputsForDevice(): " | 
 | 2856 |                             "clearing direct output profile %zu on module %zu", j, i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 2857 |                     if (profile->mSamplingRates[0] == 0) { | 
 | 2858 |                         profile->mSamplingRates.clear(); | 
 | 2859 |                         profile->mSamplingRates.add(0); | 
 | 2860 |                     } | 
 | 2861 |                     if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 2862 |                         profile->mFormats.clear(); | 
 | 2863 |                         profile->mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 2864 |                     } | 
 | 2865 |                     if (profile->mChannelMasks[0] == 0) { | 
 | 2866 |                         profile->mChannelMasks.clear(); | 
 | 2867 |                         profile->mChannelMasks.add(0); | 
 | 2868 |                     } | 
 | 2869 |                 } | 
 | 2870 |             } | 
 | 2871 |         } | 
 | 2872 |     } | 
 | 2873 |     return NO_ERROR; | 
 | 2874 | } | 
 | 2875 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2876 | status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device, | 
 | 2877 |                                                       audio_policy_dev_state_t state, | 
 | 2878 |                                                       SortedVector<audio_io_handle_t>& inputs, | 
 | 2879 |                                                       const String8 address) | 
 | 2880 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 2881 |     sp<AudioInputDescriptor> desc; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2882 |     if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { | 
 | 2883 |         // first list already open inputs that can be routed to this device | 
 | 2884 |         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 2885 |             desc = mInputs.valueAt(input_index); | 
 | 2886 |             if (desc->mProfile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) { | 
 | 2887 |                 ALOGV("checkInputsForDevice(): adding opened input %d", mInputs.keyAt(input_index)); | 
 | 2888 |                inputs.add(mInputs.keyAt(input_index)); | 
 | 2889 |             } | 
 | 2890 |         } | 
 | 2891 |  | 
 | 2892 |         // then look for input profiles that can be routed to this device | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2893 |         SortedVector< sp<IOProfile> > profiles; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2894 |         for (size_t module_idx = 0; module_idx < mHwModules.size(); module_idx++) | 
 | 2895 |         { | 
 | 2896 |             if (mHwModules[module_idx]->mHandle == 0) { | 
 | 2897 |                 continue; | 
 | 2898 |             } | 
 | 2899 |             for (size_t profile_index = 0; | 
 | 2900 |                  profile_index < mHwModules[module_idx]->mInputProfiles.size(); | 
 | 2901 |                  profile_index++) | 
 | 2902 |             { | 
 | 2903 |                 if (mHwModules[module_idx]->mInputProfiles[profile_index]->mSupportedDevices.types() | 
 | 2904 |                         & (device & ~AUDIO_DEVICE_BIT_IN)) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 2905 |                     ALOGV("checkInputsForDevice(): adding profile %zu from module %zu", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2906 |                           profile_index, module_idx); | 
 | 2907 |                     profiles.add(mHwModules[module_idx]->mInputProfiles[profile_index]); | 
 | 2908 |                 } | 
 | 2909 |             } | 
 | 2910 |         } | 
 | 2911 |  | 
 | 2912 |         if (profiles.isEmpty() && inputs.isEmpty()) { | 
 | 2913 |             ALOGW("checkInputsForDevice(): No input available for device 0x%X", device); | 
 | 2914 |             return BAD_VALUE; | 
 | 2915 |         } | 
 | 2916 |  | 
 | 2917 |         // open inputs for matching profiles if needed. Direct inputs are also opened to | 
 | 2918 |         // query for dynamic parameters and will be closed later by setDeviceConnectionState() | 
 | 2919 |         for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) { | 
 | 2920 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2921 |             sp<IOProfile> profile = profiles[profile_index]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2922 |             // nothing to do if one input is already opened for this profile | 
 | 2923 |             size_t input_index; | 
 | 2924 |             for (input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 2925 |                 desc = mInputs.valueAt(input_index); | 
 | 2926 |                 if (desc->mProfile == profile) { | 
 | 2927 |                     break; | 
 | 2928 |                 } | 
 | 2929 |             } | 
 | 2930 |             if (input_index != mInputs.size()) { | 
 | 2931 |                 continue; | 
 | 2932 |             } | 
 | 2933 |  | 
 | 2934 |             ALOGV("opening input for device 0x%X with params %s", device, address.string()); | 
 | 2935 |             desc = new AudioInputDescriptor(profile); | 
 | 2936 |             desc->mDevice = device; | 
 | 2937 |  | 
 | 2938 |             audio_io_handle_t input = mpClientInterface->openInput(profile->mModule->mHandle, | 
 | 2939 |                                             &desc->mDevice, | 
 | 2940 |                                             &desc->mSamplingRate, | 
 | 2941 |                                             &desc->mFormat, | 
| Glenn Kasten | ec40d28 | 2014-07-15 15:31:26 -0700 | [diff] [blame] | 2942 |                                             &desc->mChannelMask, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 2943 |                                             AUDIO_INPUT_FLAG_NONE /*FIXME*/); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2944 |  | 
 | 2945 |             if (input != 0) { | 
 | 2946 |                 if (!address.isEmpty()) { | 
 | 2947 |                     mpClientInterface->setParameters(input, addressToParameter(device, address)); | 
 | 2948 |                 } | 
 | 2949 |  | 
 | 2950 |                 // Here is where we step through and resolve any "dynamic" fields | 
 | 2951 |                 String8 reply; | 
 | 2952 |                 char *value; | 
 | 2953 |                 if (profile->mSamplingRates[0] == 0) { | 
 | 2954 |                     reply = mpClientInterface->getParameters(input, | 
 | 2955 |                                             String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)); | 
 | 2956 |                     ALOGV("checkInputsForDevice() direct input sup sampling rates %s", | 
 | 2957 |                               reply.string()); | 
 | 2958 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2959 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2960 |                         profile->loadSamplingRates(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2961 |                     } | 
 | 2962 |                 } | 
 | 2963 |                 if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 2964 |                     reply = mpClientInterface->getParameters(input, | 
 | 2965 |                                                    String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS)); | 
 | 2966 |                     ALOGV("checkInputsForDevice() direct input sup formats %s", reply.string()); | 
 | 2967 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2968 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2969 |                         profile->loadFormats(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2970 |                     } | 
 | 2971 |                 } | 
 | 2972 |                 if (profile->mChannelMasks[0] == 0) { | 
 | 2973 |                     reply = mpClientInterface->getParameters(input, | 
 | 2974 |                                                   String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS)); | 
 | 2975 |                     ALOGV("checkInputsForDevice() direct input sup channel masks %s", | 
 | 2976 |                               reply.string()); | 
 | 2977 |                     value = strpbrk((char *)reply.string(), "="); | 
 | 2978 |                     if (value != NULL) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 2979 |                         profile->loadInChannels(value + 1); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2980 |                     } | 
 | 2981 |                 } | 
 | 2982 |                 if (((profile->mSamplingRates[0] == 0) && (profile->mSamplingRates.size() < 2)) || | 
 | 2983 |                      ((profile->mFormats[0] == 0) && (profile->mFormats.size() < 2)) || | 
 | 2984 |                      ((profile->mChannelMasks[0] == 0) && (profile->mChannelMasks.size() < 2))) { | 
 | 2985 |                     ALOGW("checkInputsForDevice() direct input missing param"); | 
 | 2986 |                     mpClientInterface->closeInput(input); | 
 | 2987 |                     input = 0; | 
 | 2988 |                 } | 
 | 2989 |  | 
 | 2990 |                 if (input != 0) { | 
 | 2991 |                     addInput(input, desc); | 
 | 2992 |                 } | 
 | 2993 |             } // endif input != 0 | 
 | 2994 |  | 
 | 2995 |             if (input == 0) { | 
 | 2996 |                 ALOGW("checkInputsForDevice() could not open input for device 0x%X", device); | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 2997 |                 profiles.removeAt(profile_index); | 
 | 2998 |                 profile_index--; | 
 | 2999 |             } else { | 
 | 3000 |                 inputs.add(input); | 
 | 3001 |                 ALOGV("checkInputsForDevice(): adding input %d", input); | 
 | 3002 |             } | 
 | 3003 |         } // end scan profiles | 
 | 3004 |  | 
 | 3005 |         if (profiles.isEmpty()) { | 
 | 3006 |             ALOGW("checkInputsForDevice(): No input available for device 0x%X", device); | 
 | 3007 |             return BAD_VALUE; | 
 | 3008 |         } | 
 | 3009 |     } else { | 
 | 3010 |         // Disconnect | 
 | 3011 |         // check if one opened input is not needed any more after disconnecting one device | 
 | 3012 |         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { | 
 | 3013 |             desc = mInputs.valueAt(input_index); | 
 | 3014 |             if (!(desc->mProfile->mSupportedDevices.types() & mAvailableInputDevices.types())) { | 
 | 3015 |                 ALOGV("checkInputsForDevice(): disconnecting adding input %d", | 
 | 3016 |                       mInputs.keyAt(input_index)); | 
 | 3017 |                 inputs.add(mInputs.keyAt(input_index)); | 
 | 3018 |             } | 
 | 3019 |         } | 
 | 3020 |         // Clear any profiles associated with the disconnected device. | 
 | 3021 |         for (size_t module_index = 0; module_index < mHwModules.size(); module_index++) { | 
 | 3022 |             if (mHwModules[module_index]->mHandle == 0) { | 
 | 3023 |                 continue; | 
 | 3024 |             } | 
 | 3025 |             for (size_t profile_index = 0; | 
 | 3026 |                  profile_index < mHwModules[module_index]->mInputProfiles.size(); | 
 | 3027 |                  profile_index++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3028 |                 sp<IOProfile> profile = mHwModules[module_index]->mInputProfiles[profile_index]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3029 |                 if (profile->mSupportedDevices.types() & device) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 3030 |                     ALOGV("checkInputsForDevice(): clearing direct input profile %zu on module %zu", | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3031 |                           profile_index, module_index); | 
 | 3032 |                     if (profile->mSamplingRates[0] == 0) { | 
 | 3033 |                         profile->mSamplingRates.clear(); | 
 | 3034 |                         profile->mSamplingRates.add(0); | 
 | 3035 |                     } | 
 | 3036 |                     if (profile->mFormats[0] == AUDIO_FORMAT_DEFAULT) { | 
 | 3037 |                         profile->mFormats.clear(); | 
 | 3038 |                         profile->mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 3039 |                     } | 
 | 3040 |                     if (profile->mChannelMasks[0] == 0) { | 
 | 3041 |                         profile->mChannelMasks.clear(); | 
 | 3042 |                         profile->mChannelMasks.add(0); | 
 | 3043 |                     } | 
 | 3044 |                 } | 
 | 3045 |             } | 
 | 3046 |         } | 
 | 3047 |     } // end disconnect | 
 | 3048 |  | 
 | 3049 |     return NO_ERROR; | 
 | 3050 | } | 
 | 3051 |  | 
 | 3052 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3053 | void AudioPolicyManager::closeOutput(audio_io_handle_t output) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3054 | { | 
 | 3055 |     ALOGV("closeOutput(%d)", output); | 
 | 3056 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3057 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3058 |     if (outputDesc == NULL) { | 
 | 3059 |         ALOGW("closeOutput() unknown output %d", output); | 
 | 3060 |         return; | 
 | 3061 |     } | 
 | 3062 |  | 
 | 3063 |     // look for duplicated outputs connected to the output being removed. | 
 | 3064 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3065 |         sp<AudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3066 |         if (dupOutputDesc->isDuplicated() && | 
 | 3067 |                 (dupOutputDesc->mOutput1 == outputDesc || | 
 | 3068 |                 dupOutputDesc->mOutput2 == outputDesc)) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3069 |             sp<AudioOutputDescriptor> outputDesc2; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3070 |             if (dupOutputDesc->mOutput1 == outputDesc) { | 
 | 3071 |                 outputDesc2 = dupOutputDesc->mOutput2; | 
 | 3072 |             } else { | 
 | 3073 |                 outputDesc2 = dupOutputDesc->mOutput1; | 
 | 3074 |             } | 
 | 3075 |             // As all active tracks on duplicated output will be deleted, | 
 | 3076 |             // and as they were also referenced on the other output, the reference | 
 | 3077 |             // count for their stream type must be adjusted accordingly on | 
 | 3078 |             // the other output. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3079 |             for (int j = 0; j < AUDIO_STREAM_CNT; j++) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3080 |                 int refCount = dupOutputDesc->mRefCount[j]; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3081 |                 outputDesc2->changeRefCount((audio_stream_type_t)j,-refCount); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3082 |             } | 
 | 3083 |             audio_io_handle_t duplicatedOutput = mOutputs.keyAt(i); | 
 | 3084 |             ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput); | 
 | 3085 |  | 
 | 3086 |             mpClientInterface->closeOutput(duplicatedOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3087 |             mOutputs.removeItem(duplicatedOutput); | 
 | 3088 |         } | 
 | 3089 |     } | 
 | 3090 |  | 
 | 3091 |     AudioParameter param; | 
 | 3092 |     param.add(String8("closing"), String8("true")); | 
 | 3093 |     mpClientInterface->setParameters(output, param.toString()); | 
 | 3094 |  | 
 | 3095 |     mpClientInterface->closeOutput(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3096 |     mOutputs.removeItem(output); | 
 | 3097 |     mPreviousOutputs = mOutputs; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3098 |     nextAudioPortGeneration(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3099 | } | 
 | 3100 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3101 | SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device, | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3102 |                         DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3103 | { | 
 | 3104 |     SortedVector<audio_io_handle_t> outputs; | 
 | 3105 |  | 
 | 3106 |     ALOGVV("getOutputsForDevice() device %04x", device); | 
 | 3107 |     for (size_t i = 0; i < openOutputs.size(); i++) { | 
 | 3108 |         ALOGVV("output %d isDuplicated=%d device=%04x", | 
 | 3109 |                 i, openOutputs.valueAt(i)->isDuplicated(), openOutputs.valueAt(i)->supportedDevices()); | 
 | 3110 |         if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) { | 
 | 3111 |             ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i)); | 
 | 3112 |             outputs.add(openOutputs.keyAt(i)); | 
 | 3113 |         } | 
 | 3114 |     } | 
 | 3115 |     return outputs; | 
 | 3116 | } | 
 | 3117 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3118 | bool AudioPolicyManager::vectorsEqual(SortedVector<audio_io_handle_t>& outputs1, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3119 |                                    SortedVector<audio_io_handle_t>& outputs2) | 
 | 3120 | { | 
 | 3121 |     if (outputs1.size() != outputs2.size()) { | 
 | 3122 |         return false; | 
 | 3123 |     } | 
 | 3124 |     for (size_t i = 0; i < outputs1.size(); i++) { | 
 | 3125 |         if (outputs1[i] != outputs2[i]) { | 
 | 3126 |             return false; | 
 | 3127 |         } | 
 | 3128 |     } | 
 | 3129 |     return true; | 
 | 3130 | } | 
 | 3131 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3132 | void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3133 | { | 
 | 3134 |     audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/); | 
 | 3135 |     audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/); | 
 | 3136 |     SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs); | 
 | 3137 |     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs); | 
 | 3138 |  | 
 | 3139 |     if (!vectorsEqual(srcOutputs,dstOutputs)) { | 
 | 3140 |         ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d", | 
 | 3141 |               strategy, srcOutputs[0], dstOutputs[0]); | 
 | 3142 |         // mute strategy while moving tracks from one output to another | 
 | 3143 |         for (size_t i = 0; i < srcOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3144 |             sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3145 |             if (desc->isStrategyActive(strategy)) { | 
 | 3146 |                 setStrategyMute(strategy, true, srcOutputs[i]); | 
 | 3147 |                 setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); | 
 | 3148 |             } | 
 | 3149 |         } | 
 | 3150 |  | 
 | 3151 |         // Move effects associated to this strategy from previous output to new output | 
 | 3152 |         if (strategy == STRATEGY_MEDIA) { | 
 | 3153 |             audio_io_handle_t fxOutput = selectOutputForEffects(dstOutputs); | 
 | 3154 |             SortedVector<audio_io_handle_t> moved; | 
 | 3155 |             for (size_t i = 0; i < mEffects.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3156 |                 sp<EffectDescriptor> effectDesc = mEffects.valueAt(i); | 
 | 3157 |                 if (effectDesc->mSession == AUDIO_SESSION_OUTPUT_MIX && | 
 | 3158 |                         effectDesc->mIo != fxOutput) { | 
 | 3159 |                     if (moved.indexOf(effectDesc->mIo) < 0) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3160 |                         ALOGV("checkOutputForStrategy() moving effect %d to output %d", | 
 | 3161 |                               mEffects.keyAt(i), fxOutput); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3162 |                         mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, effectDesc->mIo, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3163 |                                                        fxOutput); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3164 |                         moved.add(effectDesc->mIo); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3165 |                     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3166 |                     effectDesc->mIo = fxOutput; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3167 |                 } | 
 | 3168 |             } | 
 | 3169 |         } | 
 | 3170 |         // Move tracks associated to this strategy from previous output to new output | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3171 |         for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
 | 3172 |             if (getStrategy((audio_stream_type_t)i) == strategy) { | 
 | 3173 |                 mpClientInterface->invalidateStream((audio_stream_type_t)i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3174 |             } | 
 | 3175 |         } | 
 | 3176 |     } | 
 | 3177 | } | 
 | 3178 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3179 | void AudioPolicyManager::checkOutputForAllStrategies() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3180 | { | 
 | 3181 |     checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE); | 
 | 3182 |     checkOutputForStrategy(STRATEGY_PHONE); | 
 | 3183 |     checkOutputForStrategy(STRATEGY_SONIFICATION); | 
 | 3184 |     checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 3185 |     checkOutputForStrategy(STRATEGY_MEDIA); | 
 | 3186 |     checkOutputForStrategy(STRATEGY_DTMF); | 
 | 3187 | } | 
 | 3188 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3189 | audio_io_handle_t AudioPolicyManager::getA2dpOutput() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3190 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3191 |     for (size_t i = 0; i < mOutputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3192 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3193 |         if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) { | 
 | 3194 |             return mOutputs.keyAt(i); | 
 | 3195 |         } | 
 | 3196 |     } | 
 | 3197 |  | 
 | 3198 |     return 0; | 
 | 3199 | } | 
 | 3200 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3201 | void AudioPolicyManager::checkA2dpSuspend() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3202 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3203 |     audio_io_handle_t a2dpOutput = getA2dpOutput(); | 
 | 3204 |     if (a2dpOutput == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3205 |         mA2dpSuspended = false; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3206 |         return; | 
 | 3207 |     } | 
 | 3208 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3209 |     bool isScoConnected = | 
 | 3210 |             (mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3211 |     // suspend A2DP output if: | 
 | 3212 |     //      (NOT already suspended) && | 
 | 3213 |     //      ((SCO device is connected && | 
 | 3214 |     //       (forced usage for communication || for record is SCO))) || | 
 | 3215 |     //      (phone state is ringing || in call) | 
 | 3216 |     // | 
 | 3217 |     // restore A2DP output if: | 
 | 3218 |     //      (Already suspended) && | 
 | 3219 |     //      ((SCO device is NOT connected || | 
 | 3220 |     //       (forced usage NOT for communication && NOT for record is SCO))) && | 
 | 3221 |     //      (phone state is NOT ringing && NOT in call) | 
 | 3222 |     // | 
 | 3223 |     if (mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3224 |         if ((!isScoConnected || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3225 |              ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO) && | 
 | 3226 |               (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] != AUDIO_POLICY_FORCE_BT_SCO))) && | 
 | 3227 |              ((mPhoneState != AUDIO_MODE_IN_CALL) && | 
 | 3228 |               (mPhoneState != AUDIO_MODE_RINGTONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3229 |  | 
 | 3230 |             mpClientInterface->restoreOutput(a2dpOutput); | 
 | 3231 |             mA2dpSuspended = false; | 
 | 3232 |         } | 
 | 3233 |     } else { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3234 |         if ((isScoConnected && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3235 |              ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) || | 
 | 3236 |               (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO))) || | 
 | 3237 |              ((mPhoneState == AUDIO_MODE_IN_CALL) || | 
 | 3238 |               (mPhoneState == AUDIO_MODE_RINGTONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3239 |  | 
 | 3240 |             mpClientInterface->suspendOutput(a2dpOutput); | 
 | 3241 |             mA2dpSuspended = true; | 
 | 3242 |         } | 
 | 3243 |     } | 
 | 3244 | } | 
 | 3245 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3246 | audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output, bool fromCache) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3247 | { | 
 | 3248 |     audio_devices_t device = AUDIO_DEVICE_NONE; | 
 | 3249 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3250 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3251 |  | 
 | 3252 |     ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3253 |     if (index >= 0) { | 
 | 3254 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3255 |         if (patchDesc->mUid != mUidCached) { | 
 | 3256 |             ALOGV("getNewOutputDevice() device %08x forced by patch %d", | 
 | 3257 |                   outputDesc->device(), outputDesc->mPatchHandle); | 
 | 3258 |             return outputDesc->device(); | 
 | 3259 |         } | 
 | 3260 |     } | 
 | 3261 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3262 |     // check the following by order of priority to request a routing change if necessary: | 
 | 3263 |     // 1: the strategy enforced audible is active on the output: | 
 | 3264 |     //      use device for strategy enforced audible | 
 | 3265 |     // 2: we are in call or the strategy phone is active on the output: | 
 | 3266 |     //      use device for strategy phone | 
 | 3267 |     // 3: the strategy sonification is active on the output: | 
 | 3268 |     //      use device for strategy sonification | 
 | 3269 |     // 4: the strategy "respectful" sonification is active on the output: | 
 | 3270 |     //      use device for strategy "respectful" sonification | 
 | 3271 |     // 5: the strategy media is active on the output: | 
 | 3272 |     //      use device for strategy media | 
 | 3273 |     // 6: the strategy DTMF is active on the output: | 
 | 3274 |     //      use device for strategy DTMF | 
 | 3275 |     if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) { | 
 | 3276 |         device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache); | 
 | 3277 |     } else if (isInCall() || | 
 | 3278 |                     outputDesc->isStrategyActive(STRATEGY_PHONE)) { | 
 | 3279 |         device = getDeviceForStrategy(STRATEGY_PHONE, fromCache); | 
 | 3280 |     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) { | 
 | 3281 |         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache); | 
 | 3282 |     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) { | 
 | 3283 |         device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache); | 
 | 3284 |     } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) { | 
 | 3285 |         device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache); | 
 | 3286 |     } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) { | 
 | 3287 |         device = getDeviceForStrategy(STRATEGY_DTMF, fromCache); | 
 | 3288 |     } | 
 | 3289 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3290 |     ALOGV("getNewOutputDevice() selected device %x", device); | 
 | 3291 |     return device; | 
 | 3292 | } | 
 | 3293 |  | 
 | 3294 | audio_devices_t AudioPolicyManager::getNewInputDevice(audio_io_handle_t input) | 
 | 3295 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3296 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3297 |  | 
 | 3298 |     ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 3299 |     if (index >= 0) { | 
 | 3300 |         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3301 |         if (patchDesc->mUid != mUidCached) { | 
 | 3302 |             ALOGV("getNewInputDevice() device %08x forced by patch %d", | 
 | 3303 |                   inputDesc->mDevice, inputDesc->mPatchHandle); | 
 | 3304 |             return inputDesc->mDevice; | 
 | 3305 |         } | 
 | 3306 |     } | 
 | 3307 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3308 |     audio_devices_t device = getDeviceForInputSource(inputDesc->mInputSource); | 
 | 3309 |  | 
 | 3310 |     ALOGV("getNewInputDevice() selected device %x", device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3311 |     return device; | 
 | 3312 | } | 
 | 3313 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3314 | uint32_t AudioPolicyManager::getStrategyForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3315 |     return (uint32_t)getStrategy(stream); | 
 | 3316 | } | 
 | 3317 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3318 | audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3319 |     // By checking the range of stream before calling getStrategy, we avoid | 
 | 3320 |     // getStrategy's behavior for invalid streams.  getStrategy would do a ALOGE | 
 | 3321 |     // 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] | 3322 |     if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_CNT) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3323 |         return AUDIO_DEVICE_NONE; | 
 | 3324 |     } | 
 | 3325 |     audio_devices_t devices; | 
 | 3326 |     AudioPolicyManager::routing_strategy strategy = getStrategy(stream); | 
 | 3327 |     devices = getDeviceForStrategy(strategy, true /*fromCache*/); | 
 | 3328 |     SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs); | 
 | 3329 |     for (size_t i = 0; i < outputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3330 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3331 |         if (outputDesc->isStrategyActive(strategy)) { | 
 | 3332 |             devices = outputDesc->device(); | 
 | 3333 |             break; | 
 | 3334 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3335 |     } | 
 | 3336 |     return devices; | 
 | 3337 | } | 
 | 3338 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3339 | AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3340 |         audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3341 |     // stream to strategy mapping | 
 | 3342 |     switch (stream) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3343 |     case AUDIO_STREAM_VOICE_CALL: | 
 | 3344 |     case AUDIO_STREAM_BLUETOOTH_SCO: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3345 |         return STRATEGY_PHONE; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3346 |     case AUDIO_STREAM_RING: | 
 | 3347 |     case AUDIO_STREAM_ALARM: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3348 |         return STRATEGY_SONIFICATION; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3349 |     case AUDIO_STREAM_NOTIFICATION: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3350 |         return STRATEGY_SONIFICATION_RESPECTFUL; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3351 |     case AUDIO_STREAM_DTMF: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3352 |         return STRATEGY_DTMF; | 
 | 3353 |     default: | 
 | 3354 |         ALOGE("unknown stream type"); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3355 |     case AUDIO_STREAM_SYSTEM: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3356 |         // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs | 
 | 3357 |         // while key clicks are played produces a poor result | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3358 |     case AUDIO_STREAM_TTS: | 
 | 3359 |     case AUDIO_STREAM_MUSIC: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3360 |         return STRATEGY_MEDIA; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3361 |     case AUDIO_STREAM_ENFORCED_AUDIBLE: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3362 |         return STRATEGY_ENFORCED_AUDIBLE; | 
 | 3363 |     } | 
 | 3364 | } | 
 | 3365 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 3366 | uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) { | 
 | 3367 |     // flags to strategy mapping | 
 | 3368 |     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { | 
 | 3369 |         return (uint32_t) STRATEGY_ENFORCED_AUDIBLE; | 
 | 3370 |     } | 
 | 3371 |  | 
 | 3372 |     // usage to strategy mapping | 
 | 3373 |     switch (attr->usage) { | 
 | 3374 |     case AUDIO_USAGE_MEDIA: | 
 | 3375 |     case AUDIO_USAGE_GAME: | 
 | 3376 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
 | 3377 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 3378 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 3379 |         return (uint32_t) STRATEGY_MEDIA; | 
 | 3380 |  | 
 | 3381 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 3382 |         return (uint32_t) STRATEGY_PHONE; | 
 | 3383 |  | 
 | 3384 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 3385 |         return (uint32_t) STRATEGY_DTMF; | 
 | 3386 |  | 
 | 3387 |     case AUDIO_USAGE_ALARM: | 
 | 3388 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 3389 |         return (uint32_t) STRATEGY_SONIFICATION; | 
 | 3390 |  | 
 | 3391 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 3392 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 3393 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 3394 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 3395 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 3396 |         return (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL; | 
 | 3397 |  | 
 | 3398 |     case AUDIO_USAGE_UNKNOWN: | 
 | 3399 |     default: | 
 | 3400 |         return (uint32_t) STRATEGY_MEDIA; | 
 | 3401 |     } | 
 | 3402 | } | 
 | 3403 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3404 | void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3405 |     switch(stream) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3406 |     case AUDIO_STREAM_MUSIC: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3407 |         checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL); | 
 | 3408 |         updateDevicesAndOutputs(); | 
 | 3409 |         break; | 
 | 3410 |     default: | 
 | 3411 |         break; | 
 | 3412 |     } | 
 | 3413 | } | 
 | 3414 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3415 | audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3416 |                                                              bool fromCache) | 
 | 3417 | { | 
 | 3418 |     uint32_t device = AUDIO_DEVICE_NONE; | 
 | 3419 |  | 
 | 3420 |     if (fromCache) { | 
 | 3421 |         ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x", | 
 | 3422 |               strategy, mDeviceForStrategy[strategy]); | 
 | 3423 |         return mDeviceForStrategy[strategy]; | 
 | 3424 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3425 |     audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3426 |     switch (strategy) { | 
 | 3427 |  | 
 | 3428 |     case STRATEGY_SONIFICATION_RESPECTFUL: | 
 | 3429 |         if (isInCall()) { | 
 | 3430 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3431 |         } else if (isStreamActiveRemotely(AUDIO_STREAM_MUSIC, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3432 |                 SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { | 
 | 3433 |             // while media is playing on a remote device, use the the sonification behavior. | 
 | 3434 |             // Note that we test this usecase before testing if media is playing because | 
 | 3435 |             //   the isStreamActive() method only informs about the activity of a stream, not | 
 | 3436 |             //   if it's for local playback. Note also that we use the same delay between both tests | 
 | 3437 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3438 |         } else if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3439 |             // while media is playing (or has recently played), use the same device | 
 | 3440 |             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); | 
 | 3441 |         } else { | 
 | 3442 |             // when media is not playing anymore, fall back on the sonification behavior | 
 | 3443 |             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); | 
 | 3444 |         } | 
 | 3445 |  | 
 | 3446 |         break; | 
 | 3447 |  | 
 | 3448 |     case STRATEGY_DTMF: | 
 | 3449 |         if (!isInCall()) { | 
 | 3450 |             // when off call, DTMF strategy follows the same rules as MEDIA strategy | 
 | 3451 |             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); | 
 | 3452 |             break; | 
 | 3453 |         } | 
 | 3454 |         // when in call, DTMF and PHONE strategies follow the same rules | 
 | 3455 |         // FALL THROUGH | 
 | 3456 |  | 
 | 3457 |     case STRATEGY_PHONE: | 
 | 3458 |         // for phone strategy, we first consider the forced use and then the available devices by order | 
 | 3459 |         // of priority | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3460 |         switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) { | 
 | 3461 |         case AUDIO_POLICY_FORCE_BT_SCO: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3462 |             if (!isInCall() || strategy != STRATEGY_DTMF) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3463 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3464 |                 if (device) break; | 
 | 3465 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3466 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3467 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3468 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3469 |             if (device) break; | 
 | 3470 |             // if SCO device is requested but no SCO device is available, fall back to default case | 
 | 3471 |             // FALL THROUGH | 
 | 3472 |  | 
 | 3473 |         default:    // FORCE_NONE | 
 | 3474 |             // 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] | 3475 |             if (!isInCall() && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3476 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3477 |                     (getA2dpOutput() != 0) && !mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3478 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3479 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3480 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3481 |                 if (device) break; | 
 | 3482 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3483 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3484 |             if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3485 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3486 |             if (device) break; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3487 |             if (mPhoneState != AUDIO_MODE_IN_CALL) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3488 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3489 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3490 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3491 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3492 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3493 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3494 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3495 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3496 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3497 |                 if (device) break; | 
 | 3498 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3499 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3500 |             if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3501 |             device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3502 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 3503 |                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE"); | 
 | 3504 |             } | 
 | 3505 |             break; | 
 | 3506 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3507 |         case AUDIO_POLICY_FORCE_SPEAKER: | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3508 |             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to | 
 | 3509 |             // A2DP speaker when forcing to speaker output | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3510 |             if (!isInCall() && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3511 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3512 |                     (getA2dpOutput() != 0) && !mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3513 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3514 |                 if (device) break; | 
 | 3515 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3516 |             if (mPhoneState != AUDIO_MODE_IN_CALL) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3517 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3518 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3519 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3520 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3521 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3522 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3523 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3524 |                 if (device) break; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3525 |                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3526 |                 if (device) break; | 
 | 3527 |             } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3528 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3529 |             if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3530 |             device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3531 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 3532 |                 ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER"); | 
 | 3533 |             } | 
 | 3534 |             break; | 
 | 3535 |         } | 
 | 3536 |     break; | 
 | 3537 |  | 
 | 3538 |     case STRATEGY_SONIFICATION: | 
 | 3539 |  | 
 | 3540 |         // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by | 
 | 3541 |         // handleIncallSonification(). | 
 | 3542 |         if (isInCall()) { | 
 | 3543 |             device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/); | 
 | 3544 |             break; | 
 | 3545 |         } | 
 | 3546 |         // FALL THROUGH | 
 | 3547 |  | 
 | 3548 |     case STRATEGY_ENFORCED_AUDIBLE: | 
 | 3549 |         // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION | 
 | 3550 |         // except: | 
 | 3551 |         //   - when in call where it doesn't default to STRATEGY_PHONE behavior | 
 | 3552 |         //   - in countries where not enforced in which case it follows STRATEGY_MEDIA | 
 | 3553 |  | 
 | 3554 |         if ((strategy == STRATEGY_SONIFICATION) || | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3555 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3556 |             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3557 |             if (device == AUDIO_DEVICE_NONE) { | 
 | 3558 |                 ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION"); | 
 | 3559 |             } | 
 | 3560 |         } | 
 | 3561 |         // The second device used for sonification is the same as the device used by media strategy | 
 | 3562 |         // FALL THROUGH | 
 | 3563 |  | 
 | 3564 |     case STRATEGY_MEDIA: { | 
 | 3565 |         uint32_t device2 = AUDIO_DEVICE_NONE; | 
 | 3566 |         if (strategy != STRATEGY_SONIFICATION) { | 
 | 3567 |             // no sonification on remote submix (e.g. WFD) | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3568 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3569 |         } | 
 | 3570 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3571 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3572 |                 (getA2dpOutput() != 0) && !mA2dpSuspended) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3573 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3574 |             if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3575 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3576 |             } | 
 | 3577 |             if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3578 |                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3579 |             } | 
 | 3580 |         } | 
 | 3581 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3582 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3583 |         } | 
 | 3584 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3585 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3586 |         } | 
 | 3587 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3588 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3589 |         } | 
 | 3590 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3591 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3592 |         } | 
 | 3593 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3594 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3595 |         } | 
 | 3596 |         if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { | 
 | 3597 |             // no sonification on aux digital (e.g. HDMI) | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3598 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3599 |         } | 
 | 3600 |         if ((device2 == AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3601 |                 (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3602 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3603 |         } | 
 | 3604 |         if (device2 == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3605 |             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3606 |         } | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3607 |         int device3 = AUDIO_DEVICE_NONE; | 
 | 3608 |         if (strategy == STRATEGY_MEDIA) { | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 3609 |             // ARC, SPDIF and AUX_LINE can co-exist with others. | 
| Jungshik Jang | 0c94309 | 2014-07-08 22:11:24 +0900 | [diff] [blame] | 3610 |             device3 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_HDMI_ARC; | 
 | 3611 |             device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPDIF); | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 3612 |             device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_LINE); | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3613 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3614 |  | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3615 |         device2 |= device3; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3616 |         // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or | 
 | 3617 |         // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise | 
 | 3618 |         device |= device2; | 
| Jungshik Jang | 839e4f3 | 2014-06-26 17:23:40 +0900 | [diff] [blame] | 3619 |  | 
| Jungshik Jang | 7b24ee3 | 2014-07-15 19:38:42 +0900 | [diff] [blame] | 3620 |         // If hdmi system audio mode is on, remove speaker out of output list. | 
 | 3621 |         if ((strategy == STRATEGY_MEDIA) && | 
 | 3622 |             (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] == | 
 | 3623 |                 AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { | 
 | 3624 |             device &= ~AUDIO_DEVICE_OUT_SPEAKER; | 
 | 3625 |         } | 
 | 3626 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3627 |         if (device) break; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3628 |         device = mDefaultOutputDevice->mDeviceType; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3629 |         if (device == AUDIO_DEVICE_NONE) { | 
 | 3630 |             ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA"); | 
 | 3631 |         } | 
 | 3632 |         } break; | 
 | 3633 |  | 
 | 3634 |     default: | 
 | 3635 |         ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); | 
 | 3636 |         break; | 
 | 3637 |     } | 
 | 3638 |  | 
 | 3639 |     ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); | 
 | 3640 |     return device; | 
 | 3641 | } | 
 | 3642 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3643 | void AudioPolicyManager::updateDevicesAndOutputs() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3644 | { | 
 | 3645 |     for (int i = 0; i < NUM_STRATEGIES; i++) { | 
 | 3646 |         mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); | 
 | 3647 |     } | 
 | 3648 |     mPreviousOutputs = mOutputs; | 
 | 3649 | } | 
 | 3650 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3651 | uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor> outputDesc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3652 |                                                        audio_devices_t prevDevice, | 
 | 3653 |                                                        uint32_t delayMs) | 
 | 3654 | { | 
 | 3655 |     // mute/unmute strategies using an incompatible device combination | 
 | 3656 |     // if muting, wait for the audio in pcm buffer to be drained before proceeding | 
 | 3657 |     // if unmuting, unmute only after the specified delay | 
 | 3658 |     if (outputDesc->isDuplicated()) { | 
 | 3659 |         return 0; | 
 | 3660 |     } | 
 | 3661 |  | 
 | 3662 |     uint32_t muteWaitMs = 0; | 
 | 3663 |     audio_devices_t device = outputDesc->device(); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3664 |     bool shouldMute = outputDesc->isActive() && (popcount(device) >= 2); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3665 |  | 
 | 3666 |     for (size_t i = 0; i < NUM_STRATEGIES; i++) { | 
 | 3667 |         audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/); | 
 | 3668 |         bool mute = shouldMute && (curDevice & device) && (curDevice != device); | 
 | 3669 |         bool doMute = false; | 
 | 3670 |  | 
 | 3671 |         if (mute && !outputDesc->mStrategyMutedByDevice[i]) { | 
 | 3672 |             doMute = true; | 
 | 3673 |             outputDesc->mStrategyMutedByDevice[i] = true; | 
 | 3674 |         } else if (!mute && outputDesc->mStrategyMutedByDevice[i]){ | 
 | 3675 |             doMute = true; | 
 | 3676 |             outputDesc->mStrategyMutedByDevice[i] = false; | 
 | 3677 |         } | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3678 |         if (doMute) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3679 |             for (size_t j = 0; j < mOutputs.size(); j++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3680 |                 sp<AudioOutputDescriptor> desc = mOutputs.valueAt(j); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3681 |                 // skip output if it does not share any device with current output | 
 | 3682 |                 if ((desc->supportedDevices() & outputDesc->supportedDevices()) | 
 | 3683 |                         == AUDIO_DEVICE_NONE) { | 
 | 3684 |                     continue; | 
 | 3685 |                 } | 
 | 3686 |                 audio_io_handle_t curOutput = mOutputs.keyAt(j); | 
 | 3687 |                 ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d", | 
 | 3688 |                       mute ? "muting" : "unmuting", i, curDevice, curOutput); | 
 | 3689 |                 setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs); | 
 | 3690 |                 if (desc->isStrategyActive((routing_strategy)i)) { | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3691 |                     if (mute) { | 
 | 3692 |                         // FIXME: should not need to double latency if volume could be applied | 
 | 3693 |                         // immediately by the audioflinger mixer. We must account for the delay | 
 | 3694 |                         // between now and the next time the audioflinger thread for this output | 
 | 3695 |                         // will process a buffer (which corresponds to one buffer size, | 
 | 3696 |                         // usually 1/2 or 1/4 of the latency). | 
 | 3697 |                         if (muteWaitMs < desc->latency() * 2) { | 
 | 3698 |                             muteWaitMs = desc->latency() * 2; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3699 |                         } | 
 | 3700 |                     } | 
 | 3701 |                 } | 
 | 3702 |             } | 
 | 3703 |         } | 
 | 3704 |     } | 
 | 3705 |  | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3706 |     // temporary mute output if device selection changes to avoid volume bursts due to | 
 | 3707 |     // different per device volumes | 
 | 3708 |     if (outputDesc->isActive() && (device != prevDevice)) { | 
 | 3709 |         if (muteWaitMs < outputDesc->latency() * 2) { | 
 | 3710 |             muteWaitMs = outputDesc->latency() * 2; | 
 | 3711 |         } | 
 | 3712 |         for (size_t i = 0; i < NUM_STRATEGIES; i++) { | 
 | 3713 |             if (outputDesc->isStrategyActive((routing_strategy)i)) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3714 |                 setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle); | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3715 |                 // do tempMute unmute after twice the mute wait time | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3716 |                 setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle, | 
| Eric Laurent | 9940113 | 2014-05-07 19:48:15 -0700 | [diff] [blame] | 3717 |                                 muteWaitMs *2, device); | 
 | 3718 |             } | 
 | 3719 |         } | 
 | 3720 |     } | 
 | 3721 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3722 |     // wait for the PCM output buffers to empty before proceeding with the rest of the command | 
 | 3723 |     if (muteWaitMs > delayMs) { | 
 | 3724 |         muteWaitMs -= delayMs; | 
 | 3725 |         usleep(muteWaitMs * 1000); | 
 | 3726 |         return muteWaitMs; | 
 | 3727 |     } | 
 | 3728 |     return 0; | 
 | 3729 | } | 
 | 3730 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3731 | uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3732 |                                              audio_devices_t device, | 
 | 3733 |                                              bool force, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3734 |                                              int delayMs, | 
 | 3735 |                                              audio_patch_handle_t *patchHandle) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3736 | { | 
 | 3737 |     ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3738 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3739 |     AudioParameter param; | 
 | 3740 |     uint32_t muteWaitMs; | 
 | 3741 |  | 
 | 3742 |     if (outputDesc->isDuplicated()) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3743 |         muteWaitMs = setOutputDevice(outputDesc->mOutput1->mIoHandle, device, force, delayMs); | 
 | 3744 |         muteWaitMs += setOutputDevice(outputDesc->mOutput2->mIoHandle, device, force, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3745 |         return muteWaitMs; | 
 | 3746 |     } | 
 | 3747 |     // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current | 
 | 3748 |     // output profile | 
 | 3749 |     if ((device != AUDIO_DEVICE_NONE) && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3750 |             ((device & outputDesc->mProfile->mSupportedDevices.types()) == 0)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3751 |         return 0; | 
 | 3752 |     } | 
 | 3753 |  | 
 | 3754 |     // filter devices according to output selected | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3755 |     device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3756 |  | 
 | 3757 |     audio_devices_t prevDevice = outputDesc->mDevice; | 
 | 3758 |  | 
 | 3759 |     ALOGV("setOutputDevice() prevDevice %04x", prevDevice); | 
 | 3760 |  | 
 | 3761 |     if (device != AUDIO_DEVICE_NONE) { | 
 | 3762 |         outputDesc->mDevice = device; | 
 | 3763 |     } | 
 | 3764 |     muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs); | 
 | 3765 |  | 
 | 3766 |     // Do not change the routing if: | 
 | 3767 |     //  - the requested device is AUDIO_DEVICE_NONE | 
 | 3768 |     //  - the requested device is the same as current device and force is not specified. | 
 | 3769 |     // Doing this check here allows the caller to call setOutputDevice() without conditions | 
 | 3770 |     if ((device == AUDIO_DEVICE_NONE || device == prevDevice) && !force) { | 
 | 3771 |         ALOGV("setOutputDevice() setting same device %04x or null device for output %d", device, output); | 
 | 3772 |         return muteWaitMs; | 
 | 3773 |     } | 
 | 3774 |  | 
 | 3775 |     ALOGV("setOutputDevice() changing device"); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3776 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3777 |     // do the routing | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3778 |     if (device == AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3779 |         resetOutputDevice(output, delayMs, NULL); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3780 |     } else { | 
 | 3781 |         DeviceVector deviceList = mAvailableOutputDevices.getDevicesFromType(device); | 
 | 3782 |         if (!deviceList.isEmpty()) { | 
 | 3783 |             struct audio_patch patch; | 
 | 3784 |             outputDesc->toAudioPortConfig(&patch.sources[0]); | 
 | 3785 |             patch.num_sources = 1; | 
 | 3786 |             patch.num_sinks = 0; | 
 | 3787 |             for (size_t i = 0; i < deviceList.size() && i < AUDIO_PATCH_PORTS_MAX; i++) { | 
 | 3788 |                 deviceList.itemAt(i)->toAudioPortConfig(&patch.sinks[i]); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3789 |                 patch.num_sinks++; | 
 | 3790 |             } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3791 |             ssize_t index; | 
 | 3792 |             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) { | 
 | 3793 |                 index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 3794 |             } else { | 
 | 3795 |                 index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3796 |             } | 
 | 3797 |             sp< AudioPatch> patchDesc; | 
 | 3798 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 3799 |             if (index >= 0) { | 
 | 3800 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 3801 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 3802 |             } | 
 | 3803 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3804 |             status_t status = mpClientInterface->createAudioPatch(&patch, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3805 |                                                                    &afPatchHandle, | 
 | 3806 |                                                                    delayMs); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3807 |             ALOGV("setOutputDevice() createAudioPatch returned %d patchHandle %d" | 
 | 3808 |                     "num_sources %d num_sinks %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3809 |                                        status, afPatchHandle, patch.num_sources, patch.num_sinks); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3810 |             if (status == NO_ERROR) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3811 |                 if (index < 0) { | 
 | 3812 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 3813 |                                                &patch, mUidCached); | 
 | 3814 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 3815 |                 } else { | 
 | 3816 |                     patchDesc->mPatch = patch; | 
 | 3817 |                 } | 
 | 3818 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 3819 |                 patchDesc->mUid = mUidCached; | 
 | 3820 |                 if (patchHandle) { | 
 | 3821 |                     *patchHandle = patchDesc->mHandle; | 
 | 3822 |                 } | 
 | 3823 |                 outputDesc->mPatchHandle = patchDesc->mHandle; | 
 | 3824 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 3825 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3826 |             } | 
 | 3827 |         } | 
 | 3828 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3829 |  | 
 | 3830 |     // update stream volumes according to new device | 
 | 3831 |     applyStreamVolumes(output, device, delayMs); | 
 | 3832 |  | 
 | 3833 |     return muteWaitMs; | 
 | 3834 | } | 
 | 3835 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3836 | status_t AudioPolicyManager::resetOutputDevice(audio_io_handle_t output, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3837 |                                                int delayMs, | 
 | 3838 |                                                audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3839 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3840 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3841 |     ssize_t index; | 
 | 3842 |     if (patchHandle) { | 
 | 3843 |         index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 3844 |     } else { | 
 | 3845 |         index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle); | 
 | 3846 |     } | 
 | 3847 |     if (index < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3848 |         return INVALID_OPERATION; | 
 | 3849 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3850 |     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3851 |     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3852 |     ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status); | 
 | 3853 |     outputDesc->mPatchHandle = 0; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3854 |     removeAudioPatch(patchDesc->mHandle); | 
 | 3855 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 3856 |     mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3857 |     return status; | 
 | 3858 | } | 
 | 3859 |  | 
 | 3860 | status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input, | 
 | 3861 |                                             audio_devices_t device, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3862 |                                             bool force, | 
 | 3863 |                                             audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3864 | { | 
 | 3865 |     status_t status = NO_ERROR; | 
 | 3866 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3867 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3868 |     if ((device != AUDIO_DEVICE_NONE) && ((device != inputDesc->mDevice) || force)) { | 
 | 3869 |         inputDesc->mDevice = device; | 
 | 3870 |  | 
 | 3871 |         DeviceVector deviceList = mAvailableInputDevices.getDevicesFromType(device); | 
 | 3872 |         if (!deviceList.isEmpty()) { | 
 | 3873 |             struct audio_patch patch; | 
 | 3874 |             inputDesc->toAudioPortConfig(&patch.sinks[0]); | 
| Eric Laurent | daf92cc | 2014-07-22 15:36:10 -0700 | [diff] [blame] | 3875 |             // AUDIO_SOURCE_HOTWORD is for internal use only: | 
 | 3876 |             // handled as AUDIO_SOURCE_VOICE_RECOGNITION by the audio HAL | 
 | 3877 |             if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD) { | 
 | 3878 |                 patch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_VOICE_RECOGNITION; | 
 | 3879 |             } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3880 |             patch.num_sinks = 1; | 
 | 3881 |             //only one input device for now | 
 | 3882 |             deviceList.itemAt(0)->toAudioPortConfig(&patch.sources[0]); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3883 |             patch.num_sources = 1; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3884 |             ssize_t index; | 
 | 3885 |             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) { | 
 | 3886 |                 index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 3887 |             } else { | 
 | 3888 |                 index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 3889 |             } | 
 | 3890 |             sp< AudioPatch> patchDesc; | 
 | 3891 |             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE; | 
 | 3892 |             if (index >= 0) { | 
 | 3893 |                 patchDesc = mAudioPatches.valueAt(index); | 
 | 3894 |                 afPatchHandle = patchDesc->mAfPatchHandle; | 
 | 3895 |             } | 
 | 3896 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3897 |             status_t status = mpClientInterface->createAudioPatch(&patch, | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3898 |                                                                   &afPatchHandle, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3899 |                                                                   0); | 
 | 3900 |             ALOGV("setInputDevice() createAudioPatch returned %d patchHandle %d", | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3901 |                                                                           status, afPatchHandle); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3902 |             if (status == NO_ERROR) { | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3903 |                 if (index < 0) { | 
 | 3904 |                     patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(), | 
 | 3905 |                                                &patch, mUidCached); | 
 | 3906 |                     addAudioPatch(patchDesc->mHandle, patchDesc); | 
 | 3907 |                 } else { | 
 | 3908 |                     patchDesc->mPatch = patch; | 
 | 3909 |                 } | 
 | 3910 |                 patchDesc->mAfPatchHandle = afPatchHandle; | 
 | 3911 |                 patchDesc->mUid = mUidCached; | 
 | 3912 |                 if (patchHandle) { | 
 | 3913 |                     *patchHandle = patchDesc->mHandle; | 
 | 3914 |                 } | 
 | 3915 |                 inputDesc->mPatchHandle = patchDesc->mHandle; | 
 | 3916 |                 nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 3917 |                 mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3918 |             } | 
 | 3919 |         } | 
 | 3920 |     } | 
 | 3921 |     return status; | 
 | 3922 | } | 
 | 3923 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3924 | status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input, | 
 | 3925 |                                               audio_patch_handle_t *patchHandle) | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3926 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 3927 |     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input); | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3928 |     ssize_t index; | 
 | 3929 |     if (patchHandle) { | 
 | 3930 |         index = mAudioPatches.indexOfKey(*patchHandle); | 
 | 3931 |     } else { | 
 | 3932 |         index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle); | 
 | 3933 |     } | 
 | 3934 |     if (index < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3935 |         return INVALID_OPERATION; | 
 | 3936 |     } | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3937 |     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index); | 
 | 3938 |     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3939 |     ALOGV("resetInputDevice() releaseAudioPatch returned %d", status); | 
 | 3940 |     inputDesc->mPatchHandle = 0; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 3941 |     removeAudioPatch(patchDesc->mHandle); | 
 | 3942 |     nextAudioPortGeneration(); | 
| Eric Laurent | b52c152 | 2014-05-20 11:27:36 -0700 | [diff] [blame] | 3943 |     mpClientInterface->onAudioPatchListUpdate(); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3944 |     return status; | 
 | 3945 | } | 
 | 3946 |  | 
 | 3947 | sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3948 |                                                    uint32_t samplingRate, | 
 | 3949 |                                                    audio_format_t format, | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 3950 |                                                    audio_channel_mask_t channelMask, | 
 | 3951 |                                                    audio_input_flags_t flags __unused) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3952 | { | 
 | 3953 |     // Choose an input profile based on the requested capture parameters: select the first available | 
 | 3954 |     // profile supporting all requested parameters. | 
 | 3955 |  | 
 | 3956 |     for (size_t i = 0; i < mHwModules.size(); i++) | 
 | 3957 |     { | 
 | 3958 |         if (mHwModules[i]->mHandle == 0) { | 
 | 3959 |             continue; | 
 | 3960 |         } | 
 | 3961 |         for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) | 
 | 3962 |         { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 3963 |             sp<IOProfile> profile = mHwModules[i]->mInputProfiles[j]; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 3964 |             // profile->log(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3965 |             if (profile->isCompatibleProfile(device, samplingRate, format, | 
 | 3966 |                                              channelMask, AUDIO_OUTPUT_FLAG_NONE)) { | 
 | 3967 |                 return profile; | 
 | 3968 |             } | 
 | 3969 |         } | 
 | 3970 |     } | 
 | 3971 |     return NULL; | 
 | 3972 | } | 
 | 3973 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 3974 | audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3975 | { | 
 | 3976 |     uint32_t device = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3977 |     audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & | 
 | 3978 |                                             ~AUDIO_DEVICE_BIT_IN; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3979 |     switch (inputSource) { | 
 | 3980 |     case AUDIO_SOURCE_VOICE_UPLINK: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3981 |       if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3982 |           device = AUDIO_DEVICE_IN_VOICE_CALL; | 
 | 3983 |           break; | 
 | 3984 |       } | 
 | 3985 |       // FALL THROUGH | 
 | 3986 |  | 
 | 3987 |     case AUDIO_SOURCE_DEFAULT: | 
 | 3988 |     case AUDIO_SOURCE_MIC: | 
| Mike Lockwood | 41b0e24 | 2014-05-13 15:23:35 -0700 | [diff] [blame] | 3989 |     if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) { | 
 | 3990 |         device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP; | 
 | 3991 |         break; | 
 | 3992 |     } | 
 | 3993 |     // FALL THROUGH | 
 | 3994 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 3995 |     case AUDIO_SOURCE_VOICE_RECOGNITION: | 
 | 3996 |     case AUDIO_SOURCE_HOTWORD: | 
 | 3997 |     case AUDIO_SOURCE_VOICE_COMMUNICATION: | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 3998 |         if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 3999 |                 availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4000 |             device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4001 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4002 |             device = AUDIO_DEVICE_IN_WIRED_HEADSET; | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 4003 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { | 
 | 4004 |             device = AUDIO_DEVICE_IN_USB_DEVICE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4005 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4006 |             device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 4007 |         } | 
 | 4008 |         break; | 
 | 4009 |     case AUDIO_SOURCE_CAMCORDER: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4010 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4011 |             device = AUDIO_DEVICE_IN_BACK_MIC; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4012 |         } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4013 |             device = AUDIO_DEVICE_IN_BUILTIN_MIC; | 
 | 4014 |         } | 
 | 4015 |         break; | 
 | 4016 |     case AUDIO_SOURCE_VOICE_DOWNLINK: | 
 | 4017 |     case AUDIO_SOURCE_VOICE_CALL: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4018 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4019 |             device = AUDIO_DEVICE_IN_VOICE_CALL; | 
 | 4020 |         } | 
 | 4021 |         break; | 
 | 4022 |     case AUDIO_SOURCE_REMOTE_SUBMIX: | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4023 |         if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4024 |             device = AUDIO_DEVICE_IN_REMOTE_SUBMIX; | 
 | 4025 |         } | 
 | 4026 |         break; | 
 | 4027 |     default: | 
 | 4028 |         ALOGW("getDeviceForInputSource() invalid input source %d", inputSource); | 
 | 4029 |         break; | 
 | 4030 |     } | 
 | 4031 |     ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); | 
 | 4032 |     return device; | 
 | 4033 | } | 
 | 4034 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4035 | bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4036 | { | 
 | 4037 |     if ((device & AUDIO_DEVICE_BIT_IN) != 0) { | 
 | 4038 |         device &= ~AUDIO_DEVICE_BIT_IN; | 
 | 4039 |         if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0)) | 
 | 4040 |             return true; | 
 | 4041 |     } | 
 | 4042 |     return false; | 
 | 4043 | } | 
 | 4044 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4045 | audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4046 | { | 
 | 4047 |     for (size_t i = 0; i < mInputs.size(); i++) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4048 |         const sp<AudioInputDescriptor>  input_descriptor = mInputs.valueAt(i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4049 |         if ((input_descriptor->mRefCount > 0) | 
 | 4050 |                 && (!ignoreVirtualInputs || !isVirtualInputDevice(input_descriptor->mDevice))) { | 
 | 4051 |             return mInputs.keyAt(i); | 
 | 4052 |         } | 
 | 4053 |     } | 
 | 4054 |     return 0; | 
 | 4055 | } | 
 | 4056 |  | 
 | 4057 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4058 | audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4059 | { | 
 | 4060 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 4061 |         // this happens when forcing a route update and no track is active on an output. | 
 | 4062 |         // In this case the returned category is not important. | 
 | 4063 |         device =  AUDIO_DEVICE_OUT_SPEAKER; | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4064 |     } else if (popcount(device) > 1) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4065 |         // Multiple device selection is either: | 
 | 4066 |         //  - speaker + one other device: give priority to speaker in this case. | 
 | 4067 |         //  - one A2DP device + another device: happens with duplicated output. In this case | 
 | 4068 |         // retain the device on the A2DP output as the other must not correspond to an active | 
 | 4069 |         // selection if not the speaker. | 
 | 4070 |         if (device & AUDIO_DEVICE_OUT_SPEAKER) { | 
 | 4071 |             device = AUDIO_DEVICE_OUT_SPEAKER; | 
 | 4072 |         } else { | 
 | 4073 |             device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP); | 
 | 4074 |         } | 
 | 4075 |     } | 
 | 4076 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4077 |     ALOGW_IF(popcount(device) != 1, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4078 |             "getDeviceForVolume() invalid device combination: %08x", | 
 | 4079 |             device); | 
 | 4080 |  | 
 | 4081 |     return device; | 
 | 4082 | } | 
 | 4083 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4084 | AudioPolicyManager::device_category AudioPolicyManager::getDeviceCategory(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4085 | { | 
 | 4086 |     switch(getDeviceForVolume(device)) { | 
 | 4087 |         case AUDIO_DEVICE_OUT_EARPIECE: | 
 | 4088 |             return DEVICE_CATEGORY_EARPIECE; | 
 | 4089 |         case AUDIO_DEVICE_OUT_WIRED_HEADSET: | 
 | 4090 |         case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: | 
 | 4091 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO: | 
 | 4092 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: | 
 | 4093 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: | 
 | 4094 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: | 
 | 4095 |             return DEVICE_CATEGORY_HEADSET; | 
 | 4096 |         case AUDIO_DEVICE_OUT_SPEAKER: | 
 | 4097 |         case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: | 
 | 4098 |         case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: | 
 | 4099 |         case AUDIO_DEVICE_OUT_AUX_DIGITAL: | 
 | 4100 |         case AUDIO_DEVICE_OUT_USB_ACCESSORY: | 
 | 4101 |         case AUDIO_DEVICE_OUT_USB_DEVICE: | 
 | 4102 |         case AUDIO_DEVICE_OUT_REMOTE_SUBMIX: | 
 | 4103 |         default: | 
 | 4104 |             return DEVICE_CATEGORY_SPEAKER; | 
 | 4105 |     } | 
 | 4106 | } | 
 | 4107 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4108 | float AudioPolicyManager::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4109 |         int indexInUi) | 
 | 4110 | { | 
 | 4111 |     device_category deviceCategory = getDeviceCategory(device); | 
 | 4112 |     const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory]; | 
 | 4113 |  | 
 | 4114 |     // the volume index in the UI is relative to the min and max volume indices for this stream type | 
 | 4115 |     int nbSteps = 1 + curve[VOLMAX].mIndex - | 
 | 4116 |             curve[VOLMIN].mIndex; | 
 | 4117 |     int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) / | 
 | 4118 |             (streamDesc.mIndexMax - streamDesc.mIndexMin); | 
 | 4119 |  | 
 | 4120 |     // find what part of the curve this index volume belongs to, or if it's out of bounds | 
 | 4121 |     int segment = 0; | 
 | 4122 |     if (volIdx < curve[VOLMIN].mIndex) {         // out of bounds | 
 | 4123 |         return 0.0f; | 
 | 4124 |     } else if (volIdx < curve[VOLKNEE1].mIndex) { | 
 | 4125 |         segment = 0; | 
 | 4126 |     } else if (volIdx < curve[VOLKNEE2].mIndex) { | 
 | 4127 |         segment = 1; | 
 | 4128 |     } else if (volIdx <= curve[VOLMAX].mIndex) { | 
 | 4129 |         segment = 2; | 
 | 4130 |     } else {                                                               // out of bounds | 
 | 4131 |         return 1.0f; | 
 | 4132 |     } | 
 | 4133 |  | 
 | 4134 |     // linear interpolation in the attenuation table in dB | 
 | 4135 |     float decibels = curve[segment].mDBAttenuation + | 
 | 4136 |             ((float)(volIdx - curve[segment].mIndex)) * | 
 | 4137 |                 ( (curve[segment+1].mDBAttenuation - | 
 | 4138 |                         curve[segment].mDBAttenuation) / | 
 | 4139 |                     ((float)(curve[segment+1].mIndex - | 
 | 4140 |                             curve[segment].mIndex)) ); | 
 | 4141 |  | 
 | 4142 |     float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) | 
 | 4143 |  | 
 | 4144 |     ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", | 
 | 4145 |             curve[segment].mIndex, volIdx, | 
 | 4146 |             curve[segment+1].mIndex, | 
 | 4147 |             curve[segment].mDBAttenuation, | 
 | 4148 |             decibels, | 
 | 4149 |             curve[segment+1].mDBAttenuation, | 
 | 4150 |             amplification); | 
 | 4151 |  | 
 | 4152 |     return amplification; | 
 | 4153 | } | 
 | 4154 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4155 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4156 |     AudioPolicyManager::sDefaultVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4157 |     {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f} | 
 | 4158 | }; | 
 | 4159 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4160 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4161 |     AudioPolicyManager::sDefaultMediaVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4162 |     {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f} | 
 | 4163 | }; | 
 | 4164 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4165 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4166 |     AudioPolicyManager::sSpeakerMediaVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4167 |     {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f} | 
 | 4168 | }; | 
 | 4169 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4170 | const AudioPolicyManager::VolumeCurvePoint | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 4171 |     AudioPolicyManager::sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Jean-Michel Trivi | 98c6043 | 2014-07-09 08:51:34 -0700 | [diff] [blame] | 4172 |     {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] | 4173 | }; | 
 | 4174 |  | 
 | 4175 | const AudioPolicyManager::VolumeCurvePoint | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4176 |     AudioPolicyManager::sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4177 |     {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f} | 
 | 4178 | }; | 
 | 4179 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4180 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4181 |     AudioPolicyManager::sSpeakerSonificationVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4182 |     {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f} | 
 | 4183 | }; | 
 | 4184 |  | 
 | 4185 | // AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks | 
 | 4186 | // AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets. | 
 | 4187 | // AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java). | 
 | 4188 | // The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset. | 
 | 4189 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4190 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4191 |     AudioPolicyManager::sDefaultSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4192 |     {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f} | 
 | 4193 | }; | 
 | 4194 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4195 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4196 |     AudioPolicyManager::sDefaultSystemVolumeCurveDrc[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4197 |     {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f} | 
 | 4198 | }; | 
 | 4199 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4200 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4201 |     AudioPolicyManager::sHeadsetSystemVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4202 |     {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f} | 
 | 4203 | }; | 
 | 4204 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4205 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4206 |     AudioPolicyManager::sDefaultVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4207 |     {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f} | 
 | 4208 | }; | 
 | 4209 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4210 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4211 |     AudioPolicyManager::sSpeakerVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4212 |     {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f} | 
 | 4213 | }; | 
 | 4214 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4215 | const AudioPolicyManager::VolumeCurvePoint | 
 | 4216 |             *AudioPolicyManager::sVolumeProfiles[AUDIO_STREAM_CNT] | 
 | 4217 |                                                    [AudioPolicyManager::DEVICE_CATEGORY_CNT] = { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4218 |     { // AUDIO_STREAM_VOICE_CALL | 
 | 4219 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4220 |         sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4221 |         sDefaultVoiceVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4222 |     }, | 
 | 4223 |     { // AUDIO_STREAM_SYSTEM | 
 | 4224 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4225 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4226 |         sDefaultSystemVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4227 |     }, | 
 | 4228 |     { // AUDIO_STREAM_RING | 
 | 4229 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4230 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4231 |         sDefaultVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4232 |     }, | 
 | 4233 |     { // AUDIO_STREAM_MUSIC | 
 | 4234 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4235 |         sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4236 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4237 |     }, | 
 | 4238 |     { // AUDIO_STREAM_ALARM | 
 | 4239 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4240 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4241 |         sDefaultVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4242 |     }, | 
 | 4243 |     { // AUDIO_STREAM_NOTIFICATION | 
 | 4244 |         sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4245 |         sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4246 |         sDefaultVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4247 |     }, | 
 | 4248 |     { // AUDIO_STREAM_BLUETOOTH_SCO | 
 | 4249 |         sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4250 |         sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4251 |         sDefaultVoiceVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4252 |     }, | 
 | 4253 |     { // AUDIO_STREAM_ENFORCED_AUDIBLE | 
 | 4254 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4255 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4256 |         sDefaultSystemVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4257 |     }, | 
 | 4258 |     {  // AUDIO_STREAM_DTMF | 
 | 4259 |         sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4260 |         sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4261 |         sDefaultSystemVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4262 |     }, | 
 | 4263 |     { // AUDIO_STREAM_TTS | 
 | 4264 |         sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET | 
 | 4265 |         sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER | 
 | 4266 |         sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EARPIECE | 
 | 4267 |     }, | 
 | 4268 | }; | 
 | 4269 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4270 | void AudioPolicyManager::initializeVolumeCurves() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4271 | { | 
 | 4272 |     for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
 | 4273 |         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) { | 
 | 4274 |             mStreams[i].mVolumeCurve[j] = | 
 | 4275 |                     sVolumeProfiles[i][j]; | 
 | 4276 |         } | 
 | 4277 |     } | 
 | 4278 |  | 
 | 4279 |     // Check availability of DRC on speaker path: if available, override some of the speaker curves | 
 | 4280 |     if (mSpeakerDrcEnabled) { | 
 | 4281 |         mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4282 |                 sDefaultSystemVolumeCurveDrc; | 
 | 4283 |         mStreams[AUDIO_STREAM_RING].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4284 |                 sSpeakerSonificationVolumeCurveDrc; | 
 | 4285 |         mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4286 |                 sSpeakerSonificationVolumeCurveDrc; | 
 | 4287 |         mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4288 |                 sSpeakerSonificationVolumeCurveDrc; | 
| Jean-Michel Trivi | ccd8e4a | 2014-06-05 15:33:20 -0700 | [diff] [blame] | 4289 |         mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = | 
 | 4290 |                 sSpeakerMediaVolumeCurveDrc; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4291 |     } | 
 | 4292 | } | 
 | 4293 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4294 | float AudioPolicyManager::computeVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4295 |                                             int index, | 
 | 4296 |                                             audio_io_handle_t output, | 
 | 4297 |                                             audio_devices_t device) | 
 | 4298 | { | 
 | 4299 |     float volume = 1.0; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4300 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4301 |     StreamDescriptor &streamDesc = mStreams[stream]; | 
 | 4302 |  | 
 | 4303 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 4304 |         device = outputDesc->device(); | 
 | 4305 |     } | 
 | 4306 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4307 |     volume = volIndexToAmpl(device, streamDesc, index); | 
 | 4308 |  | 
 | 4309 |     // if a headset is connected, apply the following rules to ring tones and notifications | 
 | 4310 |     // to avoid sound level bursts in user's ears: | 
 | 4311 |     // - always attenuate ring tones and notifications volume by 6dB | 
 | 4312 |     // - if music is playing, always limit the volume to current music volume, | 
 | 4313 |     // with a minimum threshold at -36dB so that notification is always perceived. | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4314 |     const routing_strategy stream_strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4315 |     if ((device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | | 
 | 4316 |             AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | | 
 | 4317 |             AUDIO_DEVICE_OUT_WIRED_HEADSET | | 
 | 4318 |             AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) && | 
 | 4319 |         ((stream_strategy == STRATEGY_SONIFICATION) | 
 | 4320 |                 || (stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL) | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4321 |                 || (stream == AUDIO_STREAM_SYSTEM) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4322 |                 || ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4323 |                     (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) && | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4324 |         streamDesc.mCanBeMuted) { | 
 | 4325 |         volume *= SONIFICATION_HEADSET_VOLUME_FACTOR; | 
 | 4326 |         // when the phone is ringing we must consider that music could have been paused just before | 
 | 4327 |         // by the music application and behave as if music was active if the last music track was | 
 | 4328 |         // just stopped | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4329 |         if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4330 |                 mLimitRingtoneVolume) { | 
 | 4331 |             audio_devices_t musicDevice = getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4332 |             float musicVol = computeVolume(AUDIO_STREAM_MUSIC, | 
 | 4333 |                                mStreams[AUDIO_STREAM_MUSIC].getVolumeIndex(musicDevice), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4334 |                                output, | 
 | 4335 |                                musicDevice); | 
 | 4336 |             float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? | 
 | 4337 |                                 musicVol : SONIFICATION_HEADSET_VOLUME_MIN; | 
 | 4338 |             if (volume > minVol) { | 
 | 4339 |                 volume = minVol; | 
 | 4340 |                 ALOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol); | 
 | 4341 |             } | 
 | 4342 |         } | 
 | 4343 |     } | 
 | 4344 |  | 
 | 4345 |     return volume; | 
 | 4346 | } | 
 | 4347 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4348 | status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4349 |                                                    int index, | 
 | 4350 |                                                    audio_io_handle_t output, | 
 | 4351 |                                                    audio_devices_t device, | 
 | 4352 |                                                    int delayMs, | 
 | 4353 |                                                    bool force) | 
 | 4354 | { | 
 | 4355 |  | 
 | 4356 |     // do not change actual stream volume if the stream is muted | 
 | 4357 |     if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { | 
 | 4358 |         ALOGVV("checkAndSetVolume() stream %d muted count %d", | 
 | 4359 |               stream, mOutputs.valueFor(output)->mMuteCount[stream]); | 
 | 4360 |         return NO_ERROR; | 
 | 4361 |     } | 
 | 4362 |  | 
 | 4363 |     // 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] | 4364 |     if ((stream == AUDIO_STREAM_VOICE_CALL && | 
 | 4365 |             mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) || | 
 | 4366 |         (stream == AUDIO_STREAM_BLUETOOTH_SCO && | 
 | 4367 |                 mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4368 |         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] | 4369 |              stream, mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4370 |         return INVALID_OPERATION; | 
 | 4371 |     } | 
 | 4372 |  | 
 | 4373 |     float volume = computeVolume(stream, index, output, device); | 
 | 4374 |     // We actually change the volume if: | 
 | 4375 |     // - the float value returned by computeVolume() changed | 
 | 4376 |     // - the force flag is set | 
 | 4377 |     if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || | 
 | 4378 |             force) { | 
 | 4379 |         mOutputs.valueFor(output)->mCurVolume[stream] = volume; | 
 | 4380 |         ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); | 
 | 4381 |         // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is | 
 | 4382 |         // enabled | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4383 |         if (stream == AUDIO_STREAM_BLUETOOTH_SCO) { | 
 | 4384 |             mpClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume, output, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4385 |         } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4386 |         mpClientInterface->setStreamVolume(stream, volume, output, delayMs); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4387 |     } | 
 | 4388 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4389 |     if (stream == AUDIO_STREAM_VOICE_CALL || | 
 | 4390 |         stream == AUDIO_STREAM_BLUETOOTH_SCO) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4391 |         float voiceVolume; | 
 | 4392 |         // 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] | 4393 |         if (stream == AUDIO_STREAM_VOICE_CALL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4394 |             voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; | 
 | 4395 |         } else { | 
 | 4396 |             voiceVolume = 1.0; | 
 | 4397 |         } | 
 | 4398 |  | 
 | 4399 |         if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) { | 
 | 4400 |             mpClientInterface->setVoiceVolume(voiceVolume, delayMs); | 
 | 4401 |             mLastVoiceVolume = voiceVolume; | 
 | 4402 |         } | 
 | 4403 |     } | 
 | 4404 |  | 
 | 4405 |     return NO_ERROR; | 
 | 4406 | } | 
 | 4407 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4408 | void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4409 |                                                 audio_devices_t device, | 
 | 4410 |                                                 int delayMs, | 
 | 4411 |                                                 bool force) | 
 | 4412 | { | 
 | 4413 |     ALOGVV("applyStreamVolumes() for output %d and device %x", output, device); | 
 | 4414 |  | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4415 |     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 4416 |         checkAndSetVolume((audio_stream_type_t)stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4417 |                           mStreams[stream].getVolumeIndex(device), | 
 | 4418 |                           output, | 
 | 4419 |                           device, | 
 | 4420 |                           delayMs, | 
 | 4421 |                           force); | 
 | 4422 |     } | 
 | 4423 | } | 
 | 4424 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4425 | void AudioPolicyManager::setStrategyMute(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4426 |                                              bool on, | 
 | 4427 |                                              audio_io_handle_t output, | 
 | 4428 |                                              int delayMs, | 
 | 4429 |                                              audio_devices_t device) | 
 | 4430 | { | 
 | 4431 |     ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4432 |     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { | 
 | 4433 |         if (getStrategy((audio_stream_type_t)stream) == strategy) { | 
 | 4434 |             setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4435 |         } | 
 | 4436 |     } | 
 | 4437 | } | 
 | 4438 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4439 | void AudioPolicyManager::setStreamMute(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4440 |                                            bool on, | 
 | 4441 |                                            audio_io_handle_t output, | 
 | 4442 |                                            int delayMs, | 
 | 4443 |                                            audio_devices_t device) | 
 | 4444 | { | 
 | 4445 |     StreamDescriptor &streamDesc = mStreams[stream]; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4446 |     sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4447 |     if (device == AUDIO_DEVICE_NONE) { | 
 | 4448 |         device = outputDesc->device(); | 
 | 4449 |     } | 
 | 4450 |  | 
 | 4451 |     ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x", | 
 | 4452 |           stream, on, output, outputDesc->mMuteCount[stream], device); | 
 | 4453 |  | 
 | 4454 |     if (on) { | 
 | 4455 |         if (outputDesc->mMuteCount[stream] == 0) { | 
 | 4456 |             if (streamDesc.mCanBeMuted && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4457 |                     ((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) || | 
 | 4458 |                      (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4459 |                 checkAndSetVolume(stream, 0, output, device, delayMs); | 
 | 4460 |             } | 
 | 4461 |         } | 
 | 4462 |         // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored | 
 | 4463 |         outputDesc->mMuteCount[stream]++; | 
 | 4464 |     } else { | 
 | 4465 |         if (outputDesc->mMuteCount[stream] == 0) { | 
 | 4466 |             ALOGV("setStreamMute() unmuting non muted stream!"); | 
 | 4467 |             return; | 
 | 4468 |         } | 
 | 4469 |         if (--outputDesc->mMuteCount[stream] == 0) { | 
 | 4470 |             checkAndSetVolume(stream, | 
 | 4471 |                               streamDesc.getVolumeIndex(device), | 
 | 4472 |                               output, | 
 | 4473 |                               device, | 
 | 4474 |                               delayMs); | 
 | 4475 |         } | 
 | 4476 |     } | 
 | 4477 | } | 
 | 4478 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4479 | void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4480 |                                                       bool starting, bool stateChange) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4481 | { | 
 | 4482 |     // if the stream pertains to sonification strategy and we are in call we must | 
 | 4483 |     // mute the stream if it is low visibility. If it is high visibility, we must play a tone | 
 | 4484 |     // in the device used for phone strategy and play the tone if the selected device does not | 
 | 4485 |     // interfere with the device used for phone strategy | 
 | 4486 |     // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as | 
 | 4487 |     // many times as there are active tracks on the output | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4488 |     const routing_strategy stream_strategy = getStrategy(stream); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4489 |     if ((stream_strategy == STRATEGY_SONIFICATION) || | 
 | 4490 |             ((stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL))) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4491 |         sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4492 |         ALOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d", | 
 | 4493 |                 stream, starting, outputDesc->mDevice, stateChange); | 
 | 4494 |         if (outputDesc->mRefCount[stream]) { | 
 | 4495 |             int muteCount = 1; | 
 | 4496 |             if (stateChange) { | 
 | 4497 |                 muteCount = outputDesc->mRefCount[stream]; | 
 | 4498 |             } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4499 |             if (audio_is_low_visibility(stream)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4500 |                 ALOGV("handleIncallSonification() low visibility, muteCount %d", muteCount); | 
 | 4501 |                 for (int i = 0; i < muteCount; i++) { | 
 | 4502 |                     setStreamMute(stream, starting, mPrimaryOutput); | 
 | 4503 |                 } | 
 | 4504 |             } else { | 
 | 4505 |                 ALOGV("handleIncallSonification() high visibility"); | 
 | 4506 |                 if (outputDesc->device() & | 
 | 4507 |                         getDeviceForStrategy(STRATEGY_PHONE, true /*fromCache*/)) { | 
 | 4508 |                     ALOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount); | 
 | 4509 |                     for (int i = 0; i < muteCount; i++) { | 
 | 4510 |                         setStreamMute(stream, starting, mPrimaryOutput); | 
 | 4511 |                     } | 
 | 4512 |                 } | 
 | 4513 |                 if (starting) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4514 |                     mpClientInterface->startTone(AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION, | 
 | 4515 |                                                  AUDIO_STREAM_VOICE_CALL); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4516 |                 } else { | 
 | 4517 |                     mpClientInterface->stopTone(); | 
 | 4518 |                 } | 
 | 4519 |             } | 
 | 4520 |         } | 
 | 4521 |     } | 
 | 4522 | } | 
 | 4523 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4524 | bool AudioPolicyManager::isInCall() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4525 | { | 
 | 4526 |     return isStateInCall(mPhoneState); | 
 | 4527 | } | 
 | 4528 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4529 | bool AudioPolicyManager::isStateInCall(int state) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4530 |     return ((state == AUDIO_MODE_IN_CALL) || | 
 | 4531 |             (state == AUDIO_MODE_IN_COMMUNICATION)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4532 | } | 
 | 4533 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4534 | uint32_t AudioPolicyManager::getMaxEffectsCpuLoad() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4535 | { | 
 | 4536 |     return MAX_EFFECTS_CPU_LOAD; | 
 | 4537 | } | 
 | 4538 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4539 | uint32_t AudioPolicyManager::getMaxEffectsMemory() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4540 | { | 
 | 4541 |     return MAX_EFFECTS_MEMORY; | 
 | 4542 | } | 
 | 4543 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4544 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4545 | // --- AudioOutputDescriptor class implementation | 
 | 4546 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4547 | AudioPolicyManager::AudioOutputDescriptor::AudioOutputDescriptor( | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4548 |         const sp<IOProfile>& profile) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4549 |     : mId(0), mIoHandle(0), mLatency(0), | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4550 |     mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4551 |     mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0) | 
 | 4552 | { | 
 | 4553 |     // clear usage count for all stream types | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4554 |     for (int i = 0; i < AUDIO_STREAM_CNT; i++) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4555 |         mRefCount[i] = 0; | 
 | 4556 |         mCurVolume[i] = -1.0; | 
 | 4557 |         mMuteCount[i] = 0; | 
 | 4558 |         mStopTime[i] = 0; | 
 | 4559 |     } | 
 | 4560 |     for (int i = 0; i < NUM_STRATEGIES; i++) { | 
 | 4561 |         mStrategyMutedByDevice[i] = false; | 
 | 4562 |     } | 
 | 4563 |     if (profile != NULL) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4564 |         mAudioPort = profile; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 4565 |         mSamplingRate = profile->pickSamplingRate(); | 
 | 4566 |         mFormat = profile->pickFormat(); | 
 | 4567 |         mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 4568 |         if (profile->mGains.size() > 0) { | 
 | 4569 |             profile->mGains[0]->getDefaultConfig(&mGain); | 
 | 4570 |         } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4571 |         mFlags = profile->mFlags; | 
 | 4572 |     } | 
 | 4573 | } | 
 | 4574 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4575 | audio_devices_t AudioPolicyManager::AudioOutputDescriptor::device() const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4576 | { | 
 | 4577 |     if (isDuplicated()) { | 
 | 4578 |         return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); | 
 | 4579 |     } else { | 
 | 4580 |         return mDevice; | 
 | 4581 |     } | 
 | 4582 | } | 
 | 4583 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4584 | uint32_t AudioPolicyManager::AudioOutputDescriptor::latency() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4585 | { | 
 | 4586 |     if (isDuplicated()) { | 
 | 4587 |         return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; | 
 | 4588 |     } else { | 
 | 4589 |         return mLatency; | 
 | 4590 |     } | 
 | 4591 | } | 
 | 4592 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4593 | bool AudioPolicyManager::AudioOutputDescriptor::sharesHwModuleWith( | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4594 |         const sp<AudioOutputDescriptor> outputDesc) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4595 | { | 
 | 4596 |     if (isDuplicated()) { | 
 | 4597 |         return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); | 
 | 4598 |     } else if (outputDesc->isDuplicated()){ | 
 | 4599 |         return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); | 
 | 4600 |     } else { | 
 | 4601 |         return (mProfile->mModule == outputDesc->mProfile->mModule); | 
 | 4602 |     } | 
 | 4603 | } | 
 | 4604 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4605 | void AudioPolicyManager::AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4606 |                                                                    int delta) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4607 | { | 
 | 4608 |     // forward usage count change to attached outputs | 
 | 4609 |     if (isDuplicated()) { | 
 | 4610 |         mOutput1->changeRefCount(stream, delta); | 
 | 4611 |         mOutput2->changeRefCount(stream, delta); | 
 | 4612 |     } | 
 | 4613 |     if ((delta + (int)mRefCount[stream]) < 0) { | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4614 |         ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", | 
 | 4615 |               delta, stream, mRefCount[stream]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4616 |         mRefCount[stream] = 0; | 
 | 4617 |         return; | 
 | 4618 |     } | 
 | 4619 |     mRefCount[stream] += delta; | 
 | 4620 |     ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); | 
 | 4621 | } | 
 | 4622 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4623 | audio_devices_t AudioPolicyManager::AudioOutputDescriptor::supportedDevices() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4624 | { | 
 | 4625 |     if (isDuplicated()) { | 
 | 4626 |         return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); | 
 | 4627 |     } else { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4628 |         return mProfile->mSupportedDevices.types() ; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4629 |     } | 
 | 4630 | } | 
 | 4631 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4632 | bool AudioPolicyManager::AudioOutputDescriptor::isActive(uint32_t inPastMs) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4633 | { | 
 | 4634 |     return isStrategyActive(NUM_STRATEGIES, inPastMs); | 
 | 4635 | } | 
 | 4636 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4637 | bool AudioPolicyManager::AudioOutputDescriptor::isStrategyActive(routing_strategy strategy, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4638 |                                                                        uint32_t inPastMs, | 
 | 4639 |                                                                        nsecs_t sysTime) const | 
 | 4640 | { | 
 | 4641 |     if ((sysTime == 0) && (inPastMs != 0)) { | 
 | 4642 |         sysTime = systemTime(); | 
 | 4643 |     } | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4644 |     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { | 
 | 4645 |         if (((getStrategy((audio_stream_type_t)i) == strategy) || | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4646 |                 (NUM_STRATEGIES == strategy)) && | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4647 |                 isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4648 |             return true; | 
 | 4649 |         } | 
 | 4650 |     } | 
 | 4651 |     return false; | 
 | 4652 | } | 
 | 4653 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4654 | bool AudioPolicyManager::AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4655 |                                                                        uint32_t inPastMs, | 
 | 4656 |                                                                        nsecs_t sysTime) const | 
 | 4657 | { | 
 | 4658 |     if (mRefCount[stream] != 0) { | 
 | 4659 |         return true; | 
 | 4660 |     } | 
 | 4661 |     if (inPastMs == 0) { | 
 | 4662 |         return false; | 
 | 4663 |     } | 
 | 4664 |     if (sysTime == 0) { | 
 | 4665 |         sysTime = systemTime(); | 
 | 4666 |     } | 
 | 4667 |     if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { | 
 | 4668 |         return true; | 
 | 4669 |     } | 
 | 4670 |     return false; | 
 | 4671 | } | 
 | 4672 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4673 | void AudioPolicyManager::AudioOutputDescriptor::toAudioPortConfig( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4674 |                                                  struct audio_port_config *dstConfig, | 
 | 4675 |                                                  const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4676 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4677 |     ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); | 
 | 4678 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4679 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| | 
 | 4680 |                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; | 
 | 4681 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4682 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4683 |     } | 
 | 4684 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 4685 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4686 |     dstConfig->id = mId; | 
 | 4687 |     dstConfig->role = AUDIO_PORT_ROLE_SOURCE; | 
 | 4688 |     dstConfig->type = AUDIO_PORT_TYPE_MIX; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4689 |     dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; | 
 | 4690 |     dstConfig->ext.mix.handle = mIoHandle; | 
 | 4691 |     dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4692 | } | 
 | 4693 |  | 
 | 4694 | void AudioPolicyManager::AudioOutputDescriptor::toAudioPort( | 
 | 4695 |                                                     struct audio_port *port) const | 
 | 4696 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4697 |     ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4698 |     mProfile->toAudioPort(port); | 
 | 4699 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4700 |     toAudioPortConfig(&port->active_config); | 
 | 4701 |     port->ext.mix.hw_module = mProfile->mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4702 |     port->ext.mix.handle = mIoHandle; | 
 | 4703 |     port->ext.mix.latency_class = | 
 | 4704 |             mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; | 
 | 4705 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4706 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4707 | status_t AudioPolicyManager::AudioOutputDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4708 | { | 
 | 4709 |     const size_t SIZE = 256; | 
 | 4710 |     char buffer[SIZE]; | 
 | 4711 |     String8 result; | 
 | 4712 |  | 
 | 4713 |     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); | 
 | 4714 |     result.append(buffer); | 
 | 4715 |     snprintf(buffer, SIZE, " Format: %08x\n", mFormat); | 
 | 4716 |     result.append(buffer); | 
 | 4717 |     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); | 
 | 4718 |     result.append(buffer); | 
 | 4719 |     snprintf(buffer, SIZE, " Latency: %d\n", mLatency); | 
 | 4720 |     result.append(buffer); | 
 | 4721 |     snprintf(buffer, SIZE, " Flags %08x\n", mFlags); | 
 | 4722 |     result.append(buffer); | 
 | 4723 |     snprintf(buffer, SIZE, " Devices %08x\n", device()); | 
 | 4724 |     result.append(buffer); | 
 | 4725 |     snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); | 
 | 4726 |     result.append(buffer); | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4727 |     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { | 
 | 4728 |         snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n", | 
 | 4729 |                  i, mCurVolume[i], mRefCount[i], mMuteCount[i]); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4730 |         result.append(buffer); | 
 | 4731 |     } | 
 | 4732 |     write(fd, result.string(), result.size()); | 
 | 4733 |  | 
 | 4734 |     return NO_ERROR; | 
 | 4735 | } | 
 | 4736 |  | 
 | 4737 | // --- AudioInputDescriptor class implementation | 
 | 4738 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4739 | AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4740 |     : mId(0), mIoHandle(0), | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4741 |       mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), mRefCount(0), | 
| Eric Laurent | 3b73df7 | 2014-03-11 09:06:29 -0700 | [diff] [blame] | 4742 |       mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4743 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4744 |     if (profile != NULL) { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4745 |         mAudioPort = profile; | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 4746 |         mSamplingRate = profile->pickSamplingRate(); | 
 | 4747 |         mFormat = profile->pickFormat(); | 
 | 4748 |         mChannelMask = profile->pickChannelMask(); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 4749 |         if (profile->mGains.size() > 0) { | 
 | 4750 |             profile->mGains[0]->getDefaultConfig(&mGain); | 
 | 4751 |         } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4752 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4753 | } | 
 | 4754 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4755 | void AudioPolicyManager::AudioInputDescriptor::toAudioPortConfig( | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4756 |                                                    struct audio_port_config *dstConfig, | 
 | 4757 |                                                    const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4758 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4759 |     ALOG_ASSERT(mProfile != 0, | 
 | 4760 |                 "toAudioPortConfig() called on input with null profile %d", mIoHandle); | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4761 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| | 
 | 4762 |                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; | 
 | 4763 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4764 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 4765 |     } | 
 | 4766 |  | 
 | 4767 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 4768 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4769 |     dstConfig->id = mId; | 
 | 4770 |     dstConfig->role = AUDIO_PORT_ROLE_SINK; | 
 | 4771 |     dstConfig->type = AUDIO_PORT_TYPE_MIX; | 
| Eric Laurent | 62aaabb | 2014-06-02 10:40:54 -0700 | [diff] [blame] | 4772 |     dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; | 
 | 4773 |     dstConfig->ext.mix.handle = mIoHandle; | 
 | 4774 |     dstConfig->ext.mix.usecase.source = mInputSource; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4775 | } | 
 | 4776 |  | 
 | 4777 | void AudioPolicyManager::AudioInputDescriptor::toAudioPort( | 
 | 4778 |                                                     struct audio_port *port) const | 
 | 4779 | { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 4780 |     ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle); | 
 | 4781 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4782 |     mProfile->toAudioPort(port); | 
 | 4783 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 4784 |     toAudioPortConfig(&port->active_config); | 
 | 4785 |     port->ext.mix.hw_module = mProfile->mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4786 |     port->ext.mix.handle = mIoHandle; | 
 | 4787 |     port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL; | 
 | 4788 | } | 
 | 4789 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4790 | status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4791 | { | 
 | 4792 |     const size_t SIZE = 256; | 
 | 4793 |     char buffer[SIZE]; | 
 | 4794 |     String8 result; | 
 | 4795 |  | 
 | 4796 |     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); | 
 | 4797 |     result.append(buffer); | 
 | 4798 |     snprintf(buffer, SIZE, " Format: %d\n", mFormat); | 
 | 4799 |     result.append(buffer); | 
 | 4800 |     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); | 
 | 4801 |     result.append(buffer); | 
 | 4802 |     snprintf(buffer, SIZE, " Devices %08x\n", mDevice); | 
 | 4803 |     result.append(buffer); | 
 | 4804 |     snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount); | 
 | 4805 |     result.append(buffer); | 
| Glenn Kasten | 6a8ab05 | 2014-07-24 14:08:35 -0700 | [diff] [blame^] | 4806 |     snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount); | 
 | 4807 |     result.append(buffer); | 
 | 4808 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4809 |     write(fd, result.string(), result.size()); | 
 | 4810 |  | 
 | 4811 |     return NO_ERROR; | 
 | 4812 | } | 
 | 4813 |  | 
 | 4814 | // --- StreamDescriptor class implementation | 
 | 4815 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4816 | AudioPolicyManager::StreamDescriptor::StreamDescriptor() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4817 |     :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true) | 
 | 4818 | { | 
 | 4819 |     mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0); | 
 | 4820 | } | 
 | 4821 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4822 | int AudioPolicyManager::StreamDescriptor::getVolumeIndex(audio_devices_t device) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4823 | { | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4824 |     device = AudioPolicyManager::getDeviceForVolume(device); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4825 |     // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT | 
 | 4826 |     if (mIndexCur.indexOfKey(device) < 0) { | 
 | 4827 |         device = AUDIO_DEVICE_OUT_DEFAULT; | 
 | 4828 |     } | 
 | 4829 |     return mIndexCur.valueFor(device); | 
 | 4830 | } | 
 | 4831 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4832 | void AudioPolicyManager::StreamDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4833 | { | 
 | 4834 |     const size_t SIZE = 256; | 
 | 4835 |     char buffer[SIZE]; | 
 | 4836 |     String8 result; | 
 | 4837 |  | 
 | 4838 |     snprintf(buffer, SIZE, "%s         %02d         %02d         ", | 
 | 4839 |              mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax); | 
 | 4840 |     result.append(buffer); | 
 | 4841 |     for (size_t i = 0; i < mIndexCur.size(); i++) { | 
 | 4842 |         snprintf(buffer, SIZE, "%04x : %02d, ", | 
 | 4843 |                  mIndexCur.keyAt(i), | 
 | 4844 |                  mIndexCur.valueAt(i)); | 
 | 4845 |         result.append(buffer); | 
 | 4846 |     } | 
 | 4847 |     result.append("\n"); | 
 | 4848 |  | 
 | 4849 |     write(fd, result.string(), result.size()); | 
 | 4850 | } | 
 | 4851 |  | 
 | 4852 | // --- EffectDescriptor class implementation | 
 | 4853 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4854 | status_t AudioPolicyManager::EffectDescriptor::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4855 | { | 
 | 4856 |     const size_t SIZE = 256; | 
 | 4857 |     char buffer[SIZE]; | 
 | 4858 |     String8 result; | 
 | 4859 |  | 
 | 4860 |     snprintf(buffer, SIZE, " I/O: %d\n", mIo); | 
 | 4861 |     result.append(buffer); | 
 | 4862 |     snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy); | 
 | 4863 |     result.append(buffer); | 
 | 4864 |     snprintf(buffer, SIZE, " Session: %d\n", mSession); | 
 | 4865 |     result.append(buffer); | 
 | 4866 |     snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name); | 
 | 4867 |     result.append(buffer); | 
 | 4868 |     snprintf(buffer, SIZE, " %s\n",  mEnabled ? "Enabled" : "Disabled"); | 
 | 4869 |     result.append(buffer); | 
 | 4870 |     write(fd, result.string(), result.size()); | 
 | 4871 |  | 
 | 4872 |     return NO_ERROR; | 
 | 4873 | } | 
 | 4874 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 4875 | // --- HwModule class implementation | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4876 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4877 | AudioPolicyManager::HwModule::HwModule(const char *name) | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 4878 |     : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)), | 
 | 4879 |       mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4880 | { | 
 | 4881 | } | 
 | 4882 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 4883 | AudioPolicyManager::HwModule::~HwModule() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4884 | { | 
 | 4885 |     for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4886 |         mOutputProfiles[i]->mSupportedDevices.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4887 |     } | 
 | 4888 |     for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 4889 |         mInputProfiles[i]->mSupportedDevices.clear(); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 4890 |     } | 
 | 4891 |     free((void *)mName); | 
 | 4892 | } | 
 | 4893 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 4894 | status_t AudioPolicyManager::HwModule::loadInput(cnode *root) | 
 | 4895 | { | 
 | 4896 |     cnode *node = root->first_child; | 
 | 4897 |  | 
 | 4898 |     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this); | 
 | 4899 |  | 
 | 4900 |     while (node) { | 
 | 4901 |         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { | 
 | 4902 |             profile->loadSamplingRates((char *)node->value); | 
 | 4903 |         } else if (strcmp(node->name, FORMATS_TAG) == 0) { | 
 | 4904 |             profile->loadFormats((char *)node->value); | 
 | 4905 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 4906 |             profile->loadInChannels((char *)node->value); | 
 | 4907 |         } else if (strcmp(node->name, DEVICES_TAG) == 0) { | 
 | 4908 |             profile->mSupportedDevices.loadDevicesFromName((char *)node->value, | 
 | 4909 |                                                            mDeclaredDevices); | 
 | 4910 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 4911 |             profile->loadGains(node); | 
 | 4912 |         } | 
 | 4913 |         node = node->next; | 
 | 4914 |     } | 
 | 4915 |     ALOGW_IF(profile->mSupportedDevices.isEmpty(), | 
 | 4916 |             "loadInput() invalid supported devices"); | 
 | 4917 |     ALOGW_IF(profile->mChannelMasks.size() == 0, | 
 | 4918 |             "loadInput() invalid supported channel masks"); | 
 | 4919 |     ALOGW_IF(profile->mSamplingRates.size() == 0, | 
 | 4920 |             "loadInput() invalid supported sampling rates"); | 
 | 4921 |     ALOGW_IF(profile->mFormats.size() == 0, | 
 | 4922 |             "loadInput() invalid supported formats"); | 
 | 4923 |     if (!profile->mSupportedDevices.isEmpty() && | 
 | 4924 |             (profile->mChannelMasks.size() != 0) && | 
 | 4925 |             (profile->mSamplingRates.size() != 0) && | 
 | 4926 |             (profile->mFormats.size() != 0)) { | 
 | 4927 |  | 
 | 4928 |         ALOGV("loadInput() adding input Supported Devices %04x", | 
 | 4929 |               profile->mSupportedDevices.types()); | 
 | 4930 |  | 
 | 4931 |         mInputProfiles.add(profile); | 
 | 4932 |         return NO_ERROR; | 
 | 4933 |     } else { | 
 | 4934 |         return BAD_VALUE; | 
 | 4935 |     } | 
 | 4936 | } | 
 | 4937 |  | 
 | 4938 | status_t AudioPolicyManager::HwModule::loadOutput(cnode *root) | 
 | 4939 | { | 
 | 4940 |     cnode *node = root->first_child; | 
 | 4941 |  | 
 | 4942 |     sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this); | 
 | 4943 |  | 
 | 4944 |     while (node) { | 
 | 4945 |         if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) { | 
 | 4946 |             profile->loadSamplingRates((char *)node->value); | 
 | 4947 |         } else if (strcmp(node->name, FORMATS_TAG) == 0) { | 
 | 4948 |             profile->loadFormats((char *)node->value); | 
 | 4949 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 4950 |             profile->loadOutChannels((char *)node->value); | 
 | 4951 |         } else if (strcmp(node->name, DEVICES_TAG) == 0) { | 
 | 4952 |             profile->mSupportedDevices.loadDevicesFromName((char *)node->value, | 
 | 4953 |                                                            mDeclaredDevices); | 
 | 4954 |         } else if (strcmp(node->name, FLAGS_TAG) == 0) { | 
 | 4955 |             profile->mFlags = parseFlagNames((char *)node->value); | 
 | 4956 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 4957 |             profile->loadGains(node); | 
 | 4958 |         } | 
 | 4959 |         node = node->next; | 
 | 4960 |     } | 
 | 4961 |     ALOGW_IF(profile->mSupportedDevices.isEmpty(), | 
 | 4962 |             "loadOutput() invalid supported devices"); | 
 | 4963 |     ALOGW_IF(profile->mChannelMasks.size() == 0, | 
 | 4964 |             "loadOutput() invalid supported channel masks"); | 
 | 4965 |     ALOGW_IF(profile->mSamplingRates.size() == 0, | 
 | 4966 |             "loadOutput() invalid supported sampling rates"); | 
 | 4967 |     ALOGW_IF(profile->mFormats.size() == 0, | 
 | 4968 |             "loadOutput() invalid supported formats"); | 
 | 4969 |     if (!profile->mSupportedDevices.isEmpty() && | 
 | 4970 |             (profile->mChannelMasks.size() != 0) && | 
 | 4971 |             (profile->mSamplingRates.size() != 0) && | 
 | 4972 |             (profile->mFormats.size() != 0)) { | 
 | 4973 |  | 
 | 4974 |         ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x", | 
 | 4975 |               profile->mSupportedDevices.types(), profile->mFlags); | 
 | 4976 |  | 
 | 4977 |         mOutputProfiles.add(profile); | 
 | 4978 |         return NO_ERROR; | 
 | 4979 |     } else { | 
 | 4980 |         return BAD_VALUE; | 
 | 4981 |     } | 
 | 4982 | } | 
 | 4983 |  | 
 | 4984 | status_t AudioPolicyManager::HwModule::loadDevice(cnode *root) | 
 | 4985 | { | 
 | 4986 |     cnode *node = root->first_child; | 
 | 4987 |  | 
 | 4988 |     audio_devices_t type = AUDIO_DEVICE_NONE; | 
 | 4989 |     while (node) { | 
 | 4990 |         if (strcmp(node->name, DEVICE_TYPE) == 0) { | 
 | 4991 |             type = parseDeviceNames((char *)node->value); | 
 | 4992 |             break; | 
 | 4993 |         } | 
 | 4994 |         node = node->next; | 
 | 4995 |     } | 
 | 4996 |     if (type == AUDIO_DEVICE_NONE || | 
 | 4997 |             (!audio_is_input_device(type) && !audio_is_output_device(type))) { | 
 | 4998 |         ALOGW("loadDevice() bad type %08x", type); | 
 | 4999 |         return BAD_VALUE; | 
 | 5000 |     } | 
 | 5001 |     sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type); | 
 | 5002 |     deviceDesc->mModule = this; | 
 | 5003 |  | 
 | 5004 |     node = root->first_child; | 
 | 5005 |     while (node) { | 
 | 5006 |         if (strcmp(node->name, DEVICE_ADDRESS) == 0) { | 
 | 5007 |             deviceDesc->mAddress = String8((char *)node->value); | 
 | 5008 |         } else if (strcmp(node->name, CHANNELS_TAG) == 0) { | 
 | 5009 |             if (audio_is_input_device(type)) { | 
 | 5010 |                 deviceDesc->loadInChannels((char *)node->value); | 
 | 5011 |             } else { | 
 | 5012 |                 deviceDesc->loadOutChannels((char *)node->value); | 
 | 5013 |             } | 
 | 5014 |         } else if (strcmp(node->name, GAINS_TAG) == 0) { | 
 | 5015 |             deviceDesc->loadGains(node); | 
 | 5016 |         } | 
 | 5017 |         node = node->next; | 
 | 5018 |     } | 
 | 5019 |  | 
 | 5020 |     ALOGV("loadDevice() adding device name %s type %08x address %s", | 
 | 5021 |           deviceDesc->mName.string(), type, deviceDesc->mAddress.string()); | 
 | 5022 |  | 
 | 5023 |     mDeclaredDevices.add(deviceDesc); | 
 | 5024 |  | 
 | 5025 |     return NO_ERROR; | 
 | 5026 | } | 
 | 5027 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5028 | void AudioPolicyManager::HwModule::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5029 | { | 
 | 5030 |     const size_t SIZE = 256; | 
 | 5031 |     char buffer[SIZE]; | 
 | 5032 |     String8 result; | 
 | 5033 |  | 
 | 5034 |     snprintf(buffer, SIZE, "  - name: %s\n", mName); | 
 | 5035 |     result.append(buffer); | 
 | 5036 |     snprintf(buffer, SIZE, "  - handle: %d\n", mHandle); | 
 | 5037 |     result.append(buffer); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 5038 |     snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF); | 
 | 5039 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5040 |     write(fd, result.string(), result.size()); | 
 | 5041 |     if (mOutputProfiles.size()) { | 
 | 5042 |         write(fd, "  - outputs:\n", strlen("  - outputs:\n")); | 
 | 5043 |         for (size_t i = 0; i < mOutputProfiles.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5044 |             snprintf(buffer, SIZE, "    output %zu:\n", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5045 |             write(fd, buffer, strlen(buffer)); | 
 | 5046 |             mOutputProfiles[i]->dump(fd); | 
 | 5047 |         } | 
 | 5048 |     } | 
 | 5049 |     if (mInputProfiles.size()) { | 
 | 5050 |         write(fd, "  - inputs:\n", strlen("  - inputs:\n")); | 
 | 5051 |         for (size_t i = 0; i < mInputProfiles.size(); i++) { | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5052 |             snprintf(buffer, SIZE, "    input %zu:\n", i); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5053 |             write(fd, buffer, strlen(buffer)); | 
 | 5054 |             mInputProfiles[i]->dump(fd); | 
 | 5055 |         } | 
 | 5056 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5057 |     if (mDeclaredDevices.size()) { | 
 | 5058 |         write(fd, "  - devices:\n", strlen("  - devices:\n")); | 
 | 5059 |         for (size_t i = 0; i < mDeclaredDevices.size(); i++) { | 
 | 5060 |             mDeclaredDevices[i]->dump(fd, 4, i); | 
 | 5061 |         } | 
 | 5062 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5063 | } | 
 | 5064 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5065 | // --- AudioPort class implementation | 
 | 5066 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5067 |  | 
 | 5068 | AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type, | 
 | 5069 |           audio_port_role_t role, const sp<HwModule>& module) : | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5070 |     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] | 5071 | { | 
 | 5072 |     mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || | 
 | 5073 |                     ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); | 
 | 5074 | } | 
 | 5075 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5076 | void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const | 
 | 5077 | { | 
 | 5078 |     port->role = mRole; | 
 | 5079 |     port->type = mType; | 
 | 5080 |     unsigned int i; | 
 | 5081 |     for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) { | 
 | 5082 |         port->sample_rates[i] = mSamplingRates[i]; | 
 | 5083 |     } | 
 | 5084 |     port->num_sample_rates = i; | 
 | 5085 |     for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) { | 
 | 5086 |         port->channel_masks[i] = mChannelMasks[i]; | 
 | 5087 |     } | 
 | 5088 |     port->num_channel_masks = i; | 
 | 5089 |     for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) { | 
 | 5090 |         port->formats[i] = mFormats[i]; | 
 | 5091 |     } | 
 | 5092 |     port->num_formats = i; | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 5093 |  | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 5094 |     ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size()); | 
| Eric Laurent | e1715a4 | 2014-05-20 11:30:42 -0700 | [diff] [blame] | 5095 |  | 
 | 5096 |     for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) { | 
 | 5097 |         port->gains[i] = mGains[i]->mGain; | 
 | 5098 |     } | 
 | 5099 |     port->num_gains = i; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5100 | } | 
 | 5101 |  | 
 | 5102 |  | 
 | 5103 | void AudioPolicyManager::AudioPort::loadSamplingRates(char *name) | 
 | 5104 | { | 
 | 5105 |     char *str = strtok(name, "|"); | 
 | 5106 |  | 
 | 5107 |     // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling | 
 | 5108 |     // rates should be read from the output stream after it is opened for the first time | 
 | 5109 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5110 |         mSamplingRates.add(0); | 
 | 5111 |         return; | 
 | 5112 |     } | 
 | 5113 |  | 
 | 5114 |     while (str != NULL) { | 
 | 5115 |         uint32_t rate = atoi(str); | 
 | 5116 |         if (rate != 0) { | 
 | 5117 |             ALOGV("loadSamplingRates() adding rate %d", rate); | 
 | 5118 |             mSamplingRates.add(rate); | 
 | 5119 |         } | 
 | 5120 |         str = strtok(NULL, "|"); | 
 | 5121 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5122 | } | 
 | 5123 |  | 
 | 5124 | void AudioPolicyManager::AudioPort::loadFormats(char *name) | 
 | 5125 | { | 
 | 5126 |     char *str = strtok(name, "|"); | 
 | 5127 |  | 
 | 5128 |     // by convention, "0' in the first entry in mFormats indicates the supported formats | 
 | 5129 |     // should be read from the output stream after it is opened for the first time | 
 | 5130 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5131 |         mFormats.add(AUDIO_FORMAT_DEFAULT); | 
 | 5132 |         return; | 
 | 5133 |     } | 
 | 5134 |  | 
 | 5135 |     while (str != NULL) { | 
 | 5136 |         audio_format_t format = (audio_format_t)stringToEnum(sFormatNameToEnumTable, | 
 | 5137 |                                                              ARRAY_SIZE(sFormatNameToEnumTable), | 
 | 5138 |                                                              str); | 
 | 5139 |         if (format != AUDIO_FORMAT_DEFAULT) { | 
 | 5140 |             mFormats.add(format); | 
 | 5141 |         } | 
 | 5142 |         str = strtok(NULL, "|"); | 
 | 5143 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5144 | } | 
 | 5145 |  | 
 | 5146 | void AudioPolicyManager::AudioPort::loadInChannels(char *name) | 
 | 5147 | { | 
 | 5148 |     const char *str = strtok(name, "|"); | 
 | 5149 |  | 
 | 5150 |     ALOGV("loadInChannels() %s", name); | 
 | 5151 |  | 
 | 5152 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5153 |         mChannelMasks.add(0); | 
 | 5154 |         return; | 
 | 5155 |     } | 
 | 5156 |  | 
 | 5157 |     while (str != NULL) { | 
 | 5158 |         audio_channel_mask_t channelMask = | 
 | 5159 |                 (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, | 
 | 5160 |                                                    ARRAY_SIZE(sInChannelsNameToEnumTable), | 
 | 5161 |                                                    str); | 
 | 5162 |         if (channelMask != 0) { | 
 | 5163 |             ALOGV("loadInChannels() adding channelMask %04x", channelMask); | 
 | 5164 |             mChannelMasks.add(channelMask); | 
 | 5165 |         } | 
 | 5166 |         str = strtok(NULL, "|"); | 
 | 5167 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5168 | } | 
 | 5169 |  | 
 | 5170 | void AudioPolicyManager::AudioPort::loadOutChannels(char *name) | 
 | 5171 | { | 
 | 5172 |     const char *str = strtok(name, "|"); | 
 | 5173 |  | 
 | 5174 |     ALOGV("loadOutChannels() %s", name); | 
 | 5175 |  | 
 | 5176 |     // by convention, "0' in the first entry in mChannelMasks indicates the supported channel | 
 | 5177 |     // masks should be read from the output stream after it is opened for the first time | 
 | 5178 |     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) { | 
 | 5179 |         mChannelMasks.add(0); | 
 | 5180 |         return; | 
 | 5181 |     } | 
 | 5182 |  | 
 | 5183 |     while (str != NULL) { | 
 | 5184 |         audio_channel_mask_t channelMask = | 
 | 5185 |                 (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, | 
 | 5186 |                                                    ARRAY_SIZE(sOutChannelsNameToEnumTable), | 
 | 5187 |                                                    str); | 
 | 5188 |         if (channelMask != 0) { | 
 | 5189 |             mChannelMasks.add(channelMask); | 
 | 5190 |         } | 
 | 5191 |         str = strtok(NULL, "|"); | 
 | 5192 |     } | 
 | 5193 |     return; | 
 | 5194 | } | 
 | 5195 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5196 | audio_gain_mode_t AudioPolicyManager::AudioPort::loadGainMode(char *name) | 
 | 5197 | { | 
 | 5198 |     const char *str = strtok(name, "|"); | 
 | 5199 |  | 
 | 5200 |     ALOGV("loadGainMode() %s", name); | 
 | 5201 |     audio_gain_mode_t mode = 0; | 
 | 5202 |     while (str != NULL) { | 
 | 5203 |         mode |= (audio_gain_mode_t)stringToEnum(sGainModeNameToEnumTable, | 
 | 5204 |                                                 ARRAY_SIZE(sGainModeNameToEnumTable), | 
 | 5205 |                                                 str); | 
 | 5206 |         str = strtok(NULL, "|"); | 
 | 5207 |     } | 
 | 5208 |     return mode; | 
 | 5209 | } | 
 | 5210 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5211 | void AudioPolicyManager::AudioPort::loadGain(cnode *root, int index) | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5212 | { | 
 | 5213 |     cnode *node = root->first_child; | 
 | 5214 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5215 |     sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5216 |  | 
 | 5217 |     while (node) { | 
 | 5218 |         if (strcmp(node->name, GAIN_MODE) == 0) { | 
 | 5219 |             gain->mGain.mode = loadGainMode((char *)node->value); | 
 | 5220 |         } else if (strcmp(node->name, GAIN_CHANNELS) == 0) { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5221 |             if (mUseInChannelMask) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5222 |                 gain->mGain.channel_mask = | 
 | 5223 |                         (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable, | 
 | 5224 |                                                            ARRAY_SIZE(sInChannelsNameToEnumTable), | 
 | 5225 |                                                            (char *)node->value); | 
 | 5226 |             } else { | 
 | 5227 |                 gain->mGain.channel_mask = | 
 | 5228 |                         (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable, | 
 | 5229 |                                                            ARRAY_SIZE(sOutChannelsNameToEnumTable), | 
 | 5230 |                                                            (char *)node->value); | 
 | 5231 |             } | 
 | 5232 |         } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) { | 
 | 5233 |             gain->mGain.min_value = atoi((char *)node->value); | 
 | 5234 |         } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) { | 
 | 5235 |             gain->mGain.max_value = atoi((char *)node->value); | 
 | 5236 |         } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) { | 
 | 5237 |             gain->mGain.default_value = atoi((char *)node->value); | 
 | 5238 |         } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) { | 
 | 5239 |             gain->mGain.step_value = atoi((char *)node->value); | 
 | 5240 |         } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) { | 
 | 5241 |             gain->mGain.min_ramp_ms = atoi((char *)node->value); | 
 | 5242 |         } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) { | 
 | 5243 |             gain->mGain.max_ramp_ms = atoi((char *)node->value); | 
 | 5244 |         } | 
 | 5245 |         node = node->next; | 
 | 5246 |     } | 
 | 5247 |  | 
 | 5248 |     ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d", | 
 | 5249 |           gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value); | 
 | 5250 |  | 
 | 5251 |     if (gain->mGain.mode == 0) { | 
 | 5252 |         return; | 
 | 5253 |     } | 
 | 5254 |     mGains.add(gain); | 
 | 5255 | } | 
 | 5256 |  | 
 | 5257 | void AudioPolicyManager::AudioPort::loadGains(cnode *root) | 
 | 5258 | { | 
 | 5259 |     cnode *node = root->first_child; | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5260 |     int index = 0; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5261 |     while (node) { | 
 | 5262 |         ALOGV("loadGains() loading gain %s", node->name); | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5263 |         loadGain(node, index++); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5264 |         node = node->next; | 
 | 5265 |     } | 
 | 5266 | } | 
 | 5267 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5268 | status_t AudioPolicyManager::AudioPort::checkSamplingRate(uint32_t samplingRate) const | 
 | 5269 | { | 
 | 5270 |     for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 5271 |         if (mSamplingRates[i] == samplingRate) { | 
 | 5272 |             return NO_ERROR; | 
 | 5273 |         } | 
 | 5274 |     } | 
 | 5275 |     return BAD_VALUE; | 
 | 5276 | } | 
 | 5277 |  | 
 | 5278 | status_t AudioPolicyManager::AudioPort::checkChannelMask(audio_channel_mask_t channelMask) const | 
 | 5279 | { | 
 | 5280 |     for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 5281 |         if (mChannelMasks[i] == channelMask) { | 
 | 5282 |             return NO_ERROR; | 
 | 5283 |         } | 
 | 5284 |     } | 
 | 5285 |     return BAD_VALUE; | 
 | 5286 | } | 
 | 5287 |  | 
 | 5288 | status_t AudioPolicyManager::AudioPort::checkFormat(audio_format_t format) const | 
 | 5289 | { | 
 | 5290 |     for (size_t i = 0; i < mFormats.size(); i ++) { | 
 | 5291 |         if (mFormats[i] == format) { | 
 | 5292 |             return NO_ERROR; | 
 | 5293 |         } | 
 | 5294 |     } | 
 | 5295 |     return BAD_VALUE; | 
 | 5296 | } | 
 | 5297 |  | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5298 |  | 
 | 5299 | uint32_t AudioPolicyManager::AudioPort::pickSamplingRate() const | 
 | 5300 | { | 
 | 5301 |     // special case for uninitialized dynamic profile | 
 | 5302 |     if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) { | 
 | 5303 |         return 0; | 
 | 5304 |     } | 
 | 5305 |  | 
 | 5306 |     uint32_t samplingRate = 0; | 
 | 5307 |     uint32_t maxRate = MAX_MIXER_SAMPLING_RATE; | 
 | 5308 |  | 
 | 5309 |     // For mixed output and inputs, use max mixer sampling rates. Do not | 
 | 5310 |     // limit sampling rate otherwise | 
 | 5311 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 5312 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 5313 |             (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)))) { | 
 | 5314 |         maxRate = UINT_MAX; | 
 | 5315 |     } | 
 | 5316 |     for (size_t i = 0; i < mSamplingRates.size(); i ++) { | 
 | 5317 |         if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) { | 
 | 5318 |             samplingRate = mSamplingRates[i]; | 
 | 5319 |         } | 
 | 5320 |     } | 
 | 5321 |     return samplingRate; | 
 | 5322 | } | 
 | 5323 |  | 
 | 5324 | audio_channel_mask_t AudioPolicyManager::AudioPort::pickChannelMask() const | 
 | 5325 | { | 
 | 5326 |     // special case for uninitialized dynamic profile | 
 | 5327 |     if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) { | 
 | 5328 |         return AUDIO_CHANNEL_NONE; | 
 | 5329 |     } | 
 | 5330 |  | 
 | 5331 |     audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE; | 
 | 5332 |     uint32_t channelCount = 0; | 
 | 5333 |     uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT; | 
 | 5334 |  | 
 | 5335 |     // For mixed output and inputs, use max mixer channel count. Do not | 
 | 5336 |     // limit channel count otherwise | 
 | 5337 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 5338 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 5339 |             (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)))) { | 
 | 5340 |         maxCount = UINT_MAX; | 
 | 5341 |     } | 
 | 5342 |     for (size_t i = 0; i < mChannelMasks.size(); i ++) { | 
 | 5343 |         uint32_t cnlCount; | 
 | 5344 |         if (mUseInChannelMask) { | 
 | 5345 |             cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]); | 
 | 5346 |         } else { | 
 | 5347 |             cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]); | 
 | 5348 |         } | 
 | 5349 |         if ((cnlCount > channelCount) && (cnlCount <= maxCount)) { | 
 | 5350 |             channelMask = mChannelMasks[i]; | 
 | 5351 |         } | 
 | 5352 |     } | 
 | 5353 |     return channelMask; | 
 | 5354 | } | 
 | 5355 |  | 
 | 5356 | const audio_format_t AudioPolicyManager::AudioPort::sPcmFormatCompareTable[] = { | 
 | 5357 |         AUDIO_FORMAT_DEFAULT, | 
 | 5358 |         AUDIO_FORMAT_PCM_16_BIT, | 
| Eric Laurent | a204994 | 2014-07-21 17:49:25 -0700 | [diff] [blame] | 5359 |         AUDIO_FORMAT_PCM_8_24_BIT, | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5360 |         AUDIO_FORMAT_PCM_24_BIT_PACKED, | 
| Eric Laurent | a204994 | 2014-07-21 17:49:25 -0700 | [diff] [blame] | 5361 |         AUDIO_FORMAT_PCM_32_BIT, | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5362 | }; | 
 | 5363 |  | 
 | 5364 | int AudioPolicyManager::AudioPort::compareFormats(audio_format_t format1, | 
 | 5365 |                                                   audio_format_t format2) | 
 | 5366 | { | 
 | 5367 |     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any | 
 | 5368 |     // compressed format and better than any PCM format. This is by design of pickFormat() | 
 | 5369 |     if (!audio_is_linear_pcm(format1)) { | 
 | 5370 |         if (!audio_is_linear_pcm(format2)) { | 
 | 5371 |             return 0; | 
 | 5372 |         } | 
 | 5373 |         return 1; | 
 | 5374 |     } | 
 | 5375 |     if (!audio_is_linear_pcm(format2)) { | 
 | 5376 |         return -1; | 
 | 5377 |     } | 
 | 5378 |  | 
 | 5379 |     int index1 = -1, index2 = -1; | 
 | 5380 |     for (size_t i = 0; | 
 | 5381 |             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1)); | 
 | 5382 |             i ++) { | 
 | 5383 |         if (sPcmFormatCompareTable[i] == format1) { | 
 | 5384 |             index1 = i; | 
 | 5385 |         } | 
 | 5386 |         if (sPcmFormatCompareTable[i] == format2) { | 
 | 5387 |             index2 = i; | 
 | 5388 |         } | 
 | 5389 |     } | 
 | 5390 |     // format1 not found => index1 < 0 => format2 > format1 | 
 | 5391 |     // format2 not found => index2 < 0 => format2 < format1 | 
 | 5392 |     return index1 - index2; | 
 | 5393 | } | 
 | 5394 |  | 
 | 5395 | audio_format_t AudioPolicyManager::AudioPort::pickFormat() const | 
 | 5396 | { | 
 | 5397 |     // special case for uninitialized dynamic profile | 
 | 5398 |     if (mFormats.size() == 1 && mFormats[0] == 0) { | 
 | 5399 |         return AUDIO_FORMAT_DEFAULT; | 
 | 5400 |     } | 
 | 5401 |  | 
 | 5402 |     audio_format_t format = AUDIO_FORMAT_DEFAULT; | 
 | 5403 |     audio_format_t bestFormat = BEST_MIXER_FORMAT; | 
 | 5404 |     // For mixed output and inputs, use best mixer output format. Do not | 
 | 5405 |     // limit format otherwise | 
 | 5406 |     if ((mType != AUDIO_PORT_TYPE_MIX) || | 
 | 5407 |             ((mRole == AUDIO_PORT_ROLE_SOURCE) && | 
 | 5408 |              (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) == 0)))) { | 
 | 5409 |         bestFormat = AUDIO_FORMAT_INVALID; | 
 | 5410 |     } | 
 | 5411 |  | 
 | 5412 |     for (size_t i = 0; i < mFormats.size(); i ++) { | 
 | 5413 |         if ((compareFormats(mFormats[i], format) > 0) && | 
 | 5414 |                 (compareFormats(mFormats[i], bestFormat) <= 0)) { | 
 | 5415 |             format = mFormats[i]; | 
 | 5416 |         } | 
 | 5417 |     } | 
 | 5418 |     return format; | 
 | 5419 | } | 
 | 5420 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5421 | status_t AudioPolicyManager::AudioPort::checkGain(const struct audio_gain_config *gainConfig, | 
 | 5422 |                                                   int index) const | 
 | 5423 | { | 
 | 5424 |     if (index < 0 || (size_t)index >= mGains.size()) { | 
 | 5425 |         return BAD_VALUE; | 
 | 5426 |     } | 
 | 5427 |     return mGains[index]->checkConfig(gainConfig); | 
 | 5428 | } | 
 | 5429 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5430 | void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const | 
 | 5431 | { | 
 | 5432 |     const size_t SIZE = 256; | 
 | 5433 |     char buffer[SIZE]; | 
 | 5434 |     String8 result; | 
 | 5435 |  | 
 | 5436 |     if (mName.size() != 0) { | 
 | 5437 |         snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); | 
 | 5438 |         result.append(buffer); | 
 | 5439 |     } | 
 | 5440 |  | 
 | 5441 |     if (mSamplingRates.size() != 0) { | 
 | 5442 |         snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, ""); | 
 | 5443 |         result.append(buffer); | 
 | 5444 |         for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5445 |             if (i == 0 && mSamplingRates[i] == 0) { | 
 | 5446 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 5447 |             } else { | 
 | 5448 |                 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); | 
 | 5449 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5450 |             result.append(buffer); | 
 | 5451 |             result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); | 
 | 5452 |         } | 
 | 5453 |         result.append("\n"); | 
 | 5454 |     } | 
 | 5455 |  | 
 | 5456 |     if (mChannelMasks.size() != 0) { | 
 | 5457 |         snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, ""); | 
 | 5458 |         result.append(buffer); | 
 | 5459 |         for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5460 |             ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]); | 
 | 5461 |  | 
 | 5462 |             if (i == 0 && mChannelMasks[i] == 0) { | 
 | 5463 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 5464 |             } else { | 
 | 5465 |                 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); | 
 | 5466 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5467 |             result.append(buffer); | 
 | 5468 |             result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); | 
 | 5469 |         } | 
 | 5470 |         result.append("\n"); | 
 | 5471 |     } | 
 | 5472 |  | 
 | 5473 |     if (mFormats.size() != 0) { | 
 | 5474 |         snprintf(buffer, SIZE, "%*s- formats: ", spaces, ""); | 
 | 5475 |         result.append(buffer); | 
 | 5476 |         for (size_t i = 0; i < mFormats.size(); i++) { | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5477 |             const char *formatStr = enumToString(sFormatNameToEnumTable, | 
 | 5478 |                                                  ARRAY_SIZE(sFormatNameToEnumTable), | 
 | 5479 |                                                  mFormats[i]); | 
 | 5480 |             if (i == 0 && strcmp(formatStr, "") == 0) { | 
 | 5481 |                 snprintf(buffer, SIZE, "Dynamic"); | 
 | 5482 |             } else { | 
 | 5483 |                 snprintf(buffer, SIZE, "%-48s", formatStr); | 
 | 5484 |             } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5485 |             result.append(buffer); | 
 | 5486 |             result.append(i == (mFormats.size() - 1) ? "" : ", "); | 
 | 5487 |         } | 
 | 5488 |         result.append("\n"); | 
 | 5489 |     } | 
 | 5490 |     write(fd, result.string(), result.size()); | 
 | 5491 |     if (mGains.size() != 0) { | 
 | 5492 |         snprintf(buffer, SIZE, "%*s- gains:\n", spaces, ""); | 
 | 5493 |         write(fd, buffer, strlen(buffer) + 1); | 
 | 5494 |         result.append(buffer); | 
 | 5495 |         for (size_t i = 0; i < mGains.size(); i++) { | 
 | 5496 |             mGains[i]->dump(fd, spaces + 2, i); | 
 | 5497 |         } | 
 | 5498 |     } | 
 | 5499 | } | 
 | 5500 |  | 
 | 5501 | // --- AudioGain class implementation | 
 | 5502 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5503 | AudioPolicyManager::AudioGain::AudioGain(int index, bool useInChannelMask) | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5504 | { | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5505 |     mIndex = index; | 
 | 5506 |     mUseInChannelMask = useInChannelMask; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5507 |     memset(&mGain, 0, sizeof(struct audio_gain)); | 
 | 5508 | } | 
 | 5509 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5510 | void AudioPolicyManager::AudioGain::getDefaultConfig(struct audio_gain_config *config) | 
 | 5511 | { | 
 | 5512 |     config->index = mIndex; | 
 | 5513 |     config->mode = mGain.mode; | 
 | 5514 |     config->channel_mask = mGain.channel_mask; | 
 | 5515 |     if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { | 
 | 5516 |         config->values[0] = mGain.default_value; | 
 | 5517 |     } else { | 
 | 5518 |         uint32_t numValues; | 
 | 5519 |         if (mUseInChannelMask) { | 
 | 5520 |             numValues = audio_channel_count_from_in_mask(mGain.channel_mask); | 
 | 5521 |         } else { | 
 | 5522 |             numValues = audio_channel_count_from_out_mask(mGain.channel_mask); | 
 | 5523 |         } | 
 | 5524 |         for (size_t i = 0; i < numValues; i++) { | 
 | 5525 |             config->values[i] = mGain.default_value; | 
 | 5526 |         } | 
 | 5527 |     } | 
 | 5528 |     if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { | 
 | 5529 |         config->ramp_duration_ms = mGain.min_ramp_ms; | 
 | 5530 |     } | 
 | 5531 | } | 
 | 5532 |  | 
 | 5533 | status_t AudioPolicyManager::AudioGain::checkConfig(const struct audio_gain_config *config) | 
 | 5534 | { | 
 | 5535 |     if ((config->mode & ~mGain.mode) != 0) { | 
 | 5536 |         return BAD_VALUE; | 
 | 5537 |     } | 
 | 5538 |     if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { | 
 | 5539 |         if ((config->values[0] < mGain.min_value) || | 
 | 5540 |                     (config->values[0] > mGain.max_value)) { | 
 | 5541 |             return BAD_VALUE; | 
 | 5542 |         } | 
 | 5543 |     } else { | 
 | 5544 |         if ((config->channel_mask & ~mGain.channel_mask) != 0) { | 
 | 5545 |             return BAD_VALUE; | 
 | 5546 |         } | 
 | 5547 |         uint32_t numValues; | 
 | 5548 |         if (mUseInChannelMask) { | 
 | 5549 |             numValues = audio_channel_count_from_in_mask(config->channel_mask); | 
 | 5550 |         } else { | 
 | 5551 |             numValues = audio_channel_count_from_out_mask(config->channel_mask); | 
 | 5552 |         } | 
 | 5553 |         for (size_t i = 0; i < numValues; i++) { | 
 | 5554 |             if ((config->values[i] < mGain.min_value) || | 
 | 5555 |                     (config->values[i] > mGain.max_value)) { | 
 | 5556 |                 return BAD_VALUE; | 
 | 5557 |             } | 
 | 5558 |         } | 
 | 5559 |     } | 
 | 5560 |     if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { | 
 | 5561 |         if ((config->ramp_duration_ms < mGain.min_ramp_ms) || | 
 | 5562 |                     (config->ramp_duration_ms > mGain.max_ramp_ms)) { | 
 | 5563 |             return BAD_VALUE; | 
 | 5564 |         } | 
 | 5565 |     } | 
 | 5566 |     return NO_ERROR; | 
 | 5567 | } | 
 | 5568 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5569 | void AudioPolicyManager::AudioGain::dump(int fd, int spaces, int index) const | 
 | 5570 | { | 
 | 5571 |     const size_t SIZE = 256; | 
 | 5572 |     char buffer[SIZE]; | 
 | 5573 |     String8 result; | 
 | 5574 |  | 
 | 5575 |     snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1); | 
 | 5576 |     result.append(buffer); | 
 | 5577 |     snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode); | 
 | 5578 |     result.append(buffer); | 
 | 5579 |     snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask); | 
 | 5580 |     result.append(buffer); | 
 | 5581 |     snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value); | 
 | 5582 |     result.append(buffer); | 
 | 5583 |     snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value); | 
 | 5584 |     result.append(buffer); | 
 | 5585 |     snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value); | 
 | 5586 |     result.append(buffer); | 
 | 5587 |     snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value); | 
 | 5588 |     result.append(buffer); | 
 | 5589 |     snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms); | 
 | 5590 |     result.append(buffer); | 
 | 5591 |     snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms); | 
 | 5592 |     result.append(buffer); | 
 | 5593 |  | 
 | 5594 |     write(fd, result.string(), result.size()); | 
 | 5595 | } | 
 | 5596 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5597 | // --- AudioPortConfig class implementation | 
 | 5598 |  | 
 | 5599 | AudioPolicyManager::AudioPortConfig::AudioPortConfig() | 
 | 5600 | { | 
 | 5601 |     mSamplingRate = 0; | 
 | 5602 |     mChannelMask = AUDIO_CHANNEL_NONE; | 
 | 5603 |     mFormat = AUDIO_FORMAT_INVALID; | 
 | 5604 |     mGain.index = -1; | 
 | 5605 | } | 
 | 5606 |  | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5607 | status_t AudioPolicyManager::AudioPortConfig::applyAudioPortConfig( | 
 | 5608 |                                                         const struct audio_port_config *config, | 
 | 5609 |                                                         struct audio_port_config *backupConfig) | 
 | 5610 | { | 
 | 5611 |     struct audio_port_config localBackupConfig; | 
 | 5612 |     status_t status = NO_ERROR; | 
 | 5613 |  | 
 | 5614 |     localBackupConfig.config_mask = config->config_mask; | 
 | 5615 |     toAudioPortConfig(&localBackupConfig); | 
 | 5616 |  | 
 | 5617 |     if (mAudioPort == 0) { | 
 | 5618 |         status = NO_INIT; | 
 | 5619 |         goto exit; | 
 | 5620 |     } | 
 | 5621 |     if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { | 
 | 5622 |         status = mAudioPort->checkSamplingRate(config->sample_rate); | 
 | 5623 |         if (status != NO_ERROR) { | 
 | 5624 |             goto exit; | 
 | 5625 |         } | 
 | 5626 |         mSamplingRate = config->sample_rate; | 
 | 5627 |     } | 
 | 5628 |     if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { | 
 | 5629 |         status = mAudioPort->checkChannelMask(config->channel_mask); | 
 | 5630 |         if (status != NO_ERROR) { | 
 | 5631 |             goto exit; | 
 | 5632 |         } | 
 | 5633 |         mChannelMask = config->channel_mask; | 
 | 5634 |     } | 
 | 5635 |     if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) { | 
 | 5636 |         status = mAudioPort->checkFormat(config->format); | 
 | 5637 |         if (status != NO_ERROR) { | 
 | 5638 |             goto exit; | 
 | 5639 |         } | 
 | 5640 |         mFormat = config->format; | 
 | 5641 |     } | 
 | 5642 |     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) { | 
 | 5643 |         status = mAudioPort->checkGain(&config->gain, config->gain.index); | 
 | 5644 |         if (status != NO_ERROR) { | 
 | 5645 |             goto exit; | 
 | 5646 |         } | 
 | 5647 |         mGain = config->gain; | 
 | 5648 |     } | 
 | 5649 |  | 
 | 5650 | exit: | 
 | 5651 |     if (status != NO_ERROR) { | 
 | 5652 |         applyAudioPortConfig(&localBackupConfig); | 
 | 5653 |     } | 
 | 5654 |     if (backupConfig != NULL) { | 
 | 5655 |         *backupConfig = localBackupConfig; | 
 | 5656 |     } | 
 | 5657 |     return status; | 
 | 5658 | } | 
 | 5659 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5660 | void AudioPolicyManager::AudioPortConfig::toAudioPortConfig( | 
 | 5661 |                                                     struct audio_port_config *dstConfig, | 
 | 5662 |                                                     const struct audio_port_config *srcConfig) const | 
 | 5663 | { | 
 | 5664 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { | 
 | 5665 |         dstConfig->sample_rate = mSamplingRate; | 
 | 5666 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) { | 
 | 5667 |             dstConfig->sample_rate = srcConfig->sample_rate; | 
 | 5668 |         } | 
 | 5669 |     } else { | 
 | 5670 |         dstConfig->sample_rate = 0; | 
 | 5671 |     } | 
 | 5672 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { | 
 | 5673 |         dstConfig->channel_mask = mChannelMask; | 
 | 5674 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) { | 
 | 5675 |             dstConfig->channel_mask = srcConfig->channel_mask; | 
 | 5676 |         } | 
 | 5677 |     } else { | 
 | 5678 |         dstConfig->channel_mask = AUDIO_CHANNEL_NONE; | 
 | 5679 |     } | 
 | 5680 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) { | 
 | 5681 |         dstConfig->format = mFormat; | 
 | 5682 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) { | 
 | 5683 |             dstConfig->format = srcConfig->format; | 
 | 5684 |         } | 
 | 5685 |     } else { | 
 | 5686 |         dstConfig->format = AUDIO_FORMAT_INVALID; | 
 | 5687 |     } | 
 | 5688 |     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) { | 
 | 5689 |         dstConfig->gain = mGain; | 
 | 5690 |         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) { | 
 | 5691 |             dstConfig->gain = srcConfig->gain; | 
 | 5692 |         } | 
 | 5693 |     } else { | 
 | 5694 |         dstConfig->gain.index = -1; | 
 | 5695 |     } | 
 | 5696 |     if (dstConfig->gain.index != -1) { | 
 | 5697 |         dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN; | 
 | 5698 |     } else { | 
 | 5699 |         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN; | 
 | 5700 |     } | 
 | 5701 | } | 
 | 5702 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5703 | // --- IOProfile class implementation | 
 | 5704 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5705 | AudioPolicyManager::IOProfile::IOProfile(const String8& name, audio_port_role_t role, | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5706 |                                          const sp<HwModule>& module) | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5707 |     : AudioPort(name, AUDIO_PORT_TYPE_MIX, role, module) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5708 | { | 
 | 5709 | } | 
 | 5710 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5711 | AudioPolicyManager::IOProfile::~IOProfile() | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5712 | { | 
 | 5713 | } | 
 | 5714 |  | 
 | 5715 | // checks if the IO profile is compatible with specified parameters. | 
 | 5716 | // Sampling rate, format and channel mask must be specified in order to | 
 | 5717 | // get a valid a match | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5718 | bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5719 |                                                             uint32_t samplingRate, | 
 | 5720 |                                                             audio_format_t format, | 
 | 5721 |                                                             audio_channel_mask_t channelMask, | 
 | 5722 |                                                             audio_output_flags_t flags) const | 
 | 5723 | { | 
 | 5724 |     if (samplingRate == 0 || !audio_is_valid_format(format) || channelMask == 0) { | 
 | 5725 |          return false; | 
 | 5726 |      } | 
 | 5727 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5728 |      if ((mSupportedDevices.types() & device) != device) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5729 |          return false; | 
 | 5730 |      } | 
 | 5731 |      if ((mFlags & flags) != flags) { | 
 | 5732 |          return false; | 
 | 5733 |      } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5734 |      if (checkSamplingRate(samplingRate) != NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5735 |          return false; | 
 | 5736 |      } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5737 |      if (checkChannelMask(channelMask) != NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5738 |          return false; | 
 | 5739 |      } | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5740 |      if (checkFormat(format) != NO_ERROR) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5741 |          return false; | 
 | 5742 |      } | 
 | 5743 |      return true; | 
 | 5744 | } | 
 | 5745 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 5746 | void AudioPolicyManager::IOProfile::dump(int fd) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5747 | { | 
 | 5748 |     const size_t SIZE = 256; | 
 | 5749 |     char buffer[SIZE]; | 
 | 5750 |     String8 result; | 
 | 5751 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5752 |     AudioPort::dump(fd, 4); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5753 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5754 |     snprintf(buffer, SIZE, "    - flags: 0x%04x\n", mFlags); | 
 | 5755 |     result.append(buffer); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5756 |     snprintf(buffer, SIZE, "    - devices:\n"); | 
 | 5757 |     result.append(buffer); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5758 |     write(fd, result.string(), result.size()); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5759 |     for (size_t i = 0; i < mSupportedDevices.size(); i++) { | 
 | 5760 |         mSupportedDevices[i]->dump(fd, 6, i); | 
 | 5761 |     } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5762 | } | 
 | 5763 |  | 
| Eric Laurent | d469296 | 2014-05-05 18:13:44 -0700 | [diff] [blame] | 5764 | void AudioPolicyManager::IOProfile::log() | 
 | 5765 | { | 
 | 5766 |     const size_t SIZE = 256; | 
 | 5767 |     char buffer[SIZE]; | 
 | 5768 |     String8 result; | 
 | 5769 |  | 
 | 5770 |     ALOGV("    - sampling rates: "); | 
 | 5771 |     for (size_t i = 0; i < mSamplingRates.size(); i++) { | 
 | 5772 |         ALOGV("  %d", mSamplingRates[i]); | 
 | 5773 |     } | 
 | 5774 |  | 
 | 5775 |     ALOGV("    - channel masks: "); | 
 | 5776 |     for (size_t i = 0; i < mChannelMasks.size(); i++) { | 
 | 5777 |         ALOGV("  0x%04x", mChannelMasks[i]); | 
 | 5778 |     } | 
 | 5779 |  | 
 | 5780 |     ALOGV("    - formats: "); | 
 | 5781 |     for (size_t i = 0; i < mFormats.size(); i++) { | 
 | 5782 |         ALOGV("  0x%08x", mFormats[i]); | 
 | 5783 |     } | 
 | 5784 |  | 
 | 5785 |     ALOGV("    - devices: 0x%04x\n", mSupportedDevices.types()); | 
 | 5786 |     ALOGV("    - flags: 0x%04x\n", mFlags); | 
 | 5787 | } | 
 | 5788 |  | 
 | 5789 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5790 | // --- DeviceDescriptor implementation | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5791 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5792 |  | 
 | 5793 | AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) : | 
 | 5794 |                      AudioPort(name, AUDIO_PORT_TYPE_DEVICE, | 
 | 5795 |                                audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK : | 
 | 5796 |                                                               AUDIO_PORT_ROLE_SOURCE, | 
 | 5797 |                              NULL), | 
| Eric Laurent | 1e693b5 | 2014-07-09 15:03:28 -0700 | [diff] [blame] | 5798 |                      mDeviceType(type), mAddress(""), mId(0) | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5799 | { | 
 | 5800 |     mAudioPort = this; | 
| Eric Laurent | a121f90 | 2014-06-03 13:32:54 -0700 | [diff] [blame] | 5801 |     if (mGains.size() > 0) { | 
 | 5802 |         mGains[0]->getDefaultConfig(&mGain); | 
 | 5803 |     } | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5804 | } | 
 | 5805 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5806 | bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5807 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5808 |     // Devices are considered equal if they: | 
 | 5809 |     // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE) | 
 | 5810 |     // - have the same address or one device does not specify the address | 
 | 5811 |     // - 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] | 5812 |     return (mDeviceType == other->mDeviceType) && | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5813 |            (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) && | 
| Eric Laurent | 2f8a36f | 2014-03-26 19:05:55 -0700 | [diff] [blame] | 5814 |            (mChannelMask == 0 || other->mChannelMask == 0 || | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5815 |                 mChannelMask == other->mChannelMask); | 
 | 5816 | } | 
 | 5817 |  | 
 | 5818 | void AudioPolicyManager::DeviceVector::refreshTypes() | 
 | 5819 | { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5820 |     mDeviceTypes = AUDIO_DEVICE_NONE; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5821 |     for(size_t i = 0; i < size(); i++) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5822 |         mDeviceTypes |= itemAt(i)->mDeviceType; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5823 |     } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5824 |     ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5825 | } | 
 | 5826 |  | 
 | 5827 | ssize_t AudioPolicyManager::DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const | 
 | 5828 | { | 
 | 5829 |     for(size_t i = 0; i < size(); i++) { | 
 | 5830 |         if (item->equals(itemAt(i))) { | 
 | 5831 |             return i; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5832 |         } | 
 | 5833 |     } | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5834 |     return -1; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5835 | } | 
 | 5836 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5837 | ssize_t AudioPolicyManager::DeviceVector::add(const sp<DeviceDescriptor>& item) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5838 | { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5839 |     ssize_t ret = indexOf(item); | 
 | 5840 |  | 
 | 5841 |     if (ret < 0) { | 
 | 5842 |         ret = SortedVector::add(item); | 
 | 5843 |         if (ret >= 0) { | 
 | 5844 |             refreshTypes(); | 
 | 5845 |         } | 
 | 5846 |     } else { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5847 |         ALOGW("DeviceVector::add device %08x already in", item->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5848 |         ret = -1; | 
 | 5849 |     } | 
 | 5850 |     return ret; | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 5851 | } | 
 | 5852 |  | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5853 | ssize_t AudioPolicyManager::DeviceVector::remove(const sp<DeviceDescriptor>& item) | 
 | 5854 | { | 
 | 5855 |     size_t i; | 
 | 5856 |     ssize_t ret = indexOf(item); | 
 | 5857 |  | 
 | 5858 |     if (ret < 0) { | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5859 |         ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5860 |     } else { | 
 | 5861 |         ret = SortedVector::removeAt(ret); | 
 | 5862 |         if (ret >= 0) { | 
 | 5863 |             refreshTypes(); | 
 | 5864 |         } | 
 | 5865 |     } | 
 | 5866 |     return ret; | 
 | 5867 | } | 
 | 5868 |  | 
 | 5869 | void AudioPolicyManager::DeviceVector::loadDevicesFromType(audio_devices_t types) | 
 | 5870 | { | 
 | 5871 |     DeviceVector deviceList; | 
 | 5872 |  | 
 | 5873 |     uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types; | 
 | 5874 |     types &= ~role_bit; | 
 | 5875 |  | 
 | 5876 |     while (types) { | 
 | 5877 |         uint32_t i = 31 - __builtin_clz(types); | 
 | 5878 |         uint32_t type = 1 << i; | 
 | 5879 |         types &= ~type; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5880 |         add(new DeviceDescriptor(String8(""), type | role_bit)); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5881 |     } | 
 | 5882 | } | 
 | 5883 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5884 | void AudioPolicyManager::DeviceVector::loadDevicesFromName(char *name, | 
 | 5885 |                                                            const DeviceVector& declaredDevices) | 
 | 5886 | { | 
 | 5887 |     char *devName = strtok(name, "|"); | 
 | 5888 |     while (devName != NULL) { | 
 | 5889 |         if (strlen(devName) != 0) { | 
 | 5890 |             audio_devices_t type = stringToEnum(sDeviceNameToEnumTable, | 
 | 5891 |                                  ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 5892 |                                  devName); | 
 | 5893 |             if (type != AUDIO_DEVICE_NONE) { | 
 | 5894 |                 add(new DeviceDescriptor(String8(""), type)); | 
 | 5895 |             } else { | 
 | 5896 |                 sp<DeviceDescriptor> deviceDesc = | 
 | 5897 |                         declaredDevices.getDeviceFromName(String8(devName)); | 
 | 5898 |                 if (deviceDesc != 0) { | 
 | 5899 |                     add(deviceDesc); | 
 | 5900 |                 } | 
 | 5901 |             } | 
 | 5902 |          } | 
 | 5903 |         devName = strtok(NULL, "|"); | 
 | 5904 |      } | 
 | 5905 | } | 
 | 5906 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5907 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDevice( | 
 | 5908 |                                                         audio_devices_t type, String8 address) const | 
 | 5909 | { | 
 | 5910 |     sp<DeviceDescriptor> device; | 
 | 5911 |     for (size_t i = 0; i < size(); i++) { | 
 | 5912 |         if (itemAt(i)->mDeviceType == type) { | 
 | 5913 |             device = itemAt(i); | 
 | 5914 |             if (itemAt(i)->mAddress = address) { | 
 | 5915 |                 break; | 
 | 5916 |             } | 
 | 5917 |         } | 
 | 5918 |     } | 
 | 5919 |     ALOGV("DeviceVector::getDevice() for type %d address %s found %p", | 
 | 5920 |           type, address.string(), device.get()); | 
 | 5921 |     return device; | 
 | 5922 | } | 
 | 5923 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5924 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromId( | 
 | 5925 |                                                                     audio_port_handle_t id) const | 
 | 5926 | { | 
 | 5927 |     sp<DeviceDescriptor> device; | 
 | 5928 |     for (size_t i = 0; i < size(); i++) { | 
| Mark Salyzyn | beb9e30 | 2014-06-18 16:33:15 -0700 | [diff] [blame] | 5929 |         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] | 5930 |         if (itemAt(i)->mId == id) { | 
 | 5931 |             device = itemAt(i); | 
 | 5932 |             break; | 
 | 5933 |         } | 
 | 5934 |     } | 
 | 5935 |     return device; | 
 | 5936 | } | 
 | 5937 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5938 | AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromType( | 
 | 5939 |                                                                         audio_devices_t type) const | 
 | 5940 | { | 
 | 5941 |     DeviceVector devices; | 
 | 5942 |     for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) { | 
 | 5943 |         if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) { | 
 | 5944 |             devices.add(itemAt(i)); | 
 | 5945 |             type &= ~itemAt(i)->mDeviceType; | 
 | 5946 |             ALOGV("DeviceVector::getDevicesFromType() for type %x found %p", | 
 | 5947 |                   itemAt(i)->mDeviceType, itemAt(i).get()); | 
 | 5948 |         } | 
 | 5949 |     } | 
 | 5950 |     return devices; | 
 | 5951 | } | 
 | 5952 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5953 | sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromName( | 
 | 5954 |         const String8& name) const | 
 | 5955 | { | 
 | 5956 |     sp<DeviceDescriptor> device; | 
 | 5957 |     for (size_t i = 0; i < size(); i++) { | 
 | 5958 |         if (itemAt(i)->mName == name) { | 
 | 5959 |             device = itemAt(i); | 
 | 5960 |             break; | 
 | 5961 |         } | 
 | 5962 |     } | 
 | 5963 |     return device; | 
 | 5964 | } | 
 | 5965 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5966 | void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig( | 
 | 5967 |                                                     struct audio_port_config *dstConfig, | 
 | 5968 |                                                     const struct audio_port_config *srcConfig) const | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5969 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5970 |     dstConfig->config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK|AUDIO_PORT_CONFIG_GAIN; | 
 | 5971 |     if (srcConfig != NULL) { | 
| Eric Laurent | 84c7024 | 2014-06-23 08:46:27 -0700 | [diff] [blame] | 5972 |         dstConfig->config_mask |= srcConfig->config_mask; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 5973 |     } | 
 | 5974 |  | 
 | 5975 |     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); | 
 | 5976 |  | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5977 |     dstConfig->id = mId; | 
 | 5978 |     dstConfig->role = audio_is_output_device(mDeviceType) ? | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5979 |                         AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5980 |     dstConfig->type = AUDIO_PORT_TYPE_DEVICE; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5981 |     dstConfig->ext.device.type = mDeviceType; | 
 | 5982 |     dstConfig->ext.device.hw_module = mModule->mHandle; | 
 | 5983 |     strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5984 | } | 
 | 5985 |  | 
 | 5986 | void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const | 
 | 5987 | { | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 5988 |     ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5989 |     AudioPort::toAudioPort(port); | 
 | 5990 |     port->id = mId; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5991 |     toAudioPortConfig(&port->active_config); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5992 |     port->ext.device.type = mDeviceType; | 
| Eric Laurent | 6a94d69 | 2014-05-20 11:18:06 -0700 | [diff] [blame] | 5993 |     port->ext.device.hw_module = mModule->mHandle; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 5994 |     strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); | 
 | 5995 | } | 
 | 5996 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 5997 | status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces, int index) const | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 5998 | { | 
 | 5999 |     const size_t SIZE = 256; | 
 | 6000 |     char buffer[SIZE]; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6001 |     String8 result; | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6002 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6003 |     snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1); | 
 | 6004 |     result.append(buffer); | 
 | 6005 |     if (mId != 0) { | 
 | 6006 |         snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId); | 
 | 6007 |         result.append(buffer); | 
 | 6008 |     } | 
 | 6009 |     snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "", | 
 | 6010 |                                               enumToString(sDeviceNameToEnumTable, | 
 | 6011 |                                                            ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6012 |                                                            mDeviceType)); | 
 | 6013 |     result.append(buffer); | 
 | 6014 |     if (mAddress.size() != 0) { | 
 | 6015 |         snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string()); | 
 | 6016 |         result.append(buffer); | 
 | 6017 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6018 |     write(fd, result.string(), result.size()); | 
 | 6019 |     AudioPort::dump(fd, spaces); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6020 |  | 
 | 6021 |     return NO_ERROR; | 
 | 6022 | } | 
 | 6023 |  | 
 | 6024 |  | 
 | 6025 | // --- audio_policy.conf file parsing | 
 | 6026 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6027 | audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6028 | { | 
 | 6029 |     uint32_t flag = 0; | 
 | 6030 |  | 
 | 6031 |     // it is OK to cast name to non const here as we are not going to use it after | 
 | 6032 |     // strtok() modifies it | 
 | 6033 |     char *flagName = strtok(name, "|"); | 
 | 6034 |     while (flagName != NULL) { | 
 | 6035 |         if (strlen(flagName) != 0) { | 
 | 6036 |             flag |= stringToEnum(sFlagNameToEnumTable, | 
 | 6037 |                                ARRAY_SIZE(sFlagNameToEnumTable), | 
 | 6038 |                                flagName); | 
 | 6039 |         } | 
 | 6040 |         flagName = strtok(NULL, "|"); | 
 | 6041 |     } | 
 | 6042 |     //force direct flag if offload flag is set: offloading implies a direct output stream | 
 | 6043 |     // and all common behaviors are driven by checking only the direct flag | 
 | 6044 |     // this should normally be set appropriately in the policy configuration file | 
 | 6045 |     if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { | 
 | 6046 |         flag |= AUDIO_OUTPUT_FLAG_DIRECT; | 
 | 6047 |     } | 
 | 6048 |  | 
 | 6049 |     return (audio_output_flags_t)flag; | 
 | 6050 | } | 
 | 6051 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6052 | audio_devices_t AudioPolicyManager::parseDeviceNames(char *name) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6053 | { | 
 | 6054 |     uint32_t device = 0; | 
 | 6055 |  | 
 | 6056 |     char *devName = strtok(name, "|"); | 
 | 6057 |     while (devName != NULL) { | 
 | 6058 |         if (strlen(devName) != 0) { | 
 | 6059 |             device |= stringToEnum(sDeviceNameToEnumTable, | 
 | 6060 |                                  ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6061 |                                  devName); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6062 |          } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6063 |         devName = strtok(NULL, "|"); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6064 |      } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6065 |     return device; | 
 | 6066 | } | 
 | 6067 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6068 | void AudioPolicyManager::loadHwModule(cnode *root) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6069 | { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6070 |     status_t status = NAME_NOT_FOUND; | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6071 |     cnode *node; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6072 |     sp<HwModule> module = new HwModule(root->name); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6073 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6074 |     node = config_find(root, DEVICES_TAG); | 
 | 6075 |     if (node != NULL) { | 
 | 6076 |         node = node->first_child; | 
 | 6077 |         while (node) { | 
 | 6078 |             ALOGV("loadHwModule() loading device %s", node->name); | 
 | 6079 |             status_t tmpStatus = module->loadDevice(node); | 
 | 6080 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 6081 |                 status = tmpStatus; | 
 | 6082 |             } | 
 | 6083 |             node = node->next; | 
 | 6084 |         } | 
 | 6085 |     } | 
 | 6086 |     node = config_find(root, OUTPUTS_TAG); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6087 |     if (node != NULL) { | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6088 |         node = node->first_child; | 
 | 6089 |         while (node) { | 
 | 6090 |             ALOGV("loadHwModule() loading output %s", node->name); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6091 |             status_t tmpStatus = module->loadOutput(node); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6092 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 6093 |                 status = tmpStatus; | 
 | 6094 |             } | 
 | 6095 |             node = node->next; | 
 | 6096 |         } | 
 | 6097 |     } | 
 | 6098 |     node = config_find(root, INPUTS_TAG); | 
 | 6099 |     if (node != NULL) { | 
 | 6100 |         node = node->first_child; | 
 | 6101 |         while (node) { | 
 | 6102 |             ALOGV("loadHwModule() loading input %s", node->name); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6103 |             status_t tmpStatus = module->loadInput(node); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6104 |             if (status == NAME_NOT_FOUND || status == NO_ERROR) { | 
 | 6105 |                 status = tmpStatus; | 
 | 6106 |             } | 
 | 6107 |             node = node->next; | 
 | 6108 |         } | 
 | 6109 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6110 |     loadGlobalConfig(root, module); | 
 | 6111 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6112 |     if (status == NO_ERROR) { | 
 | 6113 |         mHwModules.add(module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6114 |     } | 
 | 6115 | } | 
 | 6116 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6117 | void AudioPolicyManager::loadHwModules(cnode *root) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6118 | { | 
 | 6119 |     cnode *node = config_find(root, AUDIO_HW_MODULE_TAG); | 
 | 6120 |     if (node == NULL) { | 
 | 6121 |         return; | 
 | 6122 |     } | 
 | 6123 |  | 
 | 6124 |     node = node->first_child; | 
 | 6125 |     while (node) { | 
 | 6126 |         ALOGV("loadHwModules() loading module %s", node->name); | 
 | 6127 |         loadHwModule(node); | 
 | 6128 |         node = node->next; | 
 | 6129 |     } | 
 | 6130 | } | 
 | 6131 |  | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6132 | void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6133 | { | 
 | 6134 |     cnode *node = config_find(root, GLOBAL_CONFIG_TAG); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 6135 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6136 |     if (node == NULL) { | 
 | 6137 |         return; | 
 | 6138 |     } | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6139 |     DeviceVector declaredDevices; | 
 | 6140 |     if (module != NULL) { | 
 | 6141 |         declaredDevices = module->mDeclaredDevices; | 
 | 6142 |     } | 
 | 6143 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6144 |     node = node->first_child; | 
 | 6145 |     while (node) { | 
 | 6146 |         if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6147 |             mAvailableOutputDevices.loadDevicesFromName((char *)node->value, | 
 | 6148 |                                                         declaredDevices); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6149 |             ALOGV("loadGlobalConfig() Attached Output Devices %08x", | 
 | 6150 |                   mAvailableOutputDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6151 |         } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) { | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6152 |             audio_devices_t device = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable, | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6153 |                                               ARRAY_SIZE(sDeviceNameToEnumTable), | 
 | 6154 |                                               (char *)node->value); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6155 |             if (device != AUDIO_DEVICE_NONE) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6156 |                 mDefaultOutputDevice = new DeviceDescriptor(String8(""), device); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6157 |             } else { | 
 | 6158 |                 ALOGW("loadGlobalConfig() default device not specified"); | 
 | 6159 |             } | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6160 |             ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6161 |         } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6162 |             mAvailableInputDevices.loadDevicesFromName((char *)node->value, | 
 | 6163 |                                                        declaredDevices); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6164 |             ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types()); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6165 |         } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { | 
 | 6166 |             mSpeakerDrcEnabled = stringToBool((char *)node->value); | 
 | 6167 |             ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled); | 
| Eric Laurent | eb108a4 | 2014-06-06 14:56:52 -0700 | [diff] [blame] | 6168 |         } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) { | 
 | 6169 |             uint32_t major, minor; | 
 | 6170 |             sscanf((char *)node->value, "%u.%u", &major, &minor); | 
 | 6171 |             module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor); | 
 | 6172 |             ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u", | 
 | 6173 |                   module->mHalVersion, major, minor); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6174 |         } | 
 | 6175 |         node = node->next; | 
 | 6176 |     } | 
 | 6177 | } | 
 | 6178 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6179 | status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6180 | { | 
 | 6181 |     cnode *root; | 
 | 6182 |     char *data; | 
 | 6183 |  | 
 | 6184 |     data = (char *)load_file(path, NULL); | 
 | 6185 |     if (data == NULL) { | 
 | 6186 |         return -ENODEV; | 
 | 6187 |     } | 
 | 6188 |     root = config_node("", ""); | 
 | 6189 |     config_load(root, data); | 
 | 6190 |  | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6191 |     loadHwModules(root); | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6192 |     // legacy audio_policy.conf files have one global_configuration section | 
 | 6193 |     loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6194 |     config_free(root); | 
 | 6195 |     free(root); | 
 | 6196 |     free(data); | 
 | 6197 |  | 
 | 6198 |     ALOGI("loadAudioPolicyConfig() loaded %s\n", path); | 
 | 6199 |  | 
 | 6200 |     return NO_ERROR; | 
 | 6201 | } | 
 | 6202 |  | 
| Eric Laurent | e072087 | 2014-03-11 09:30:41 -0700 | [diff] [blame] | 6203 | void AudioPolicyManager::defaultAudioPolicyConfig(void) | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6204 | { | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6205 |     sp<HwModule> module; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 6206 |     sp<IOProfile> profile; | 
| Eric Laurent | 1f2f223 | 2014-06-02 12:01:23 -0700 | [diff] [blame] | 6207 |     sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""), | 
 | 6208 |                                                                    AUDIO_DEVICE_IN_BUILTIN_MIC); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6209 |     mAvailableOutputDevices.add(mDefaultOutputDevice); | 
 | 6210 |     mAvailableInputDevices.add(defaultInputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6211 |  | 
 | 6212 |     module = new HwModule("primary"); | 
 | 6213 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6214 |     profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SOURCE, module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6215 |     profile->mSamplingRates.add(44100); | 
 | 6216 |     profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); | 
 | 6217 |     profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6218 |     profile->mSupportedDevices.add(mDefaultOutputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6219 |     profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY; | 
 | 6220 |     module->mOutputProfiles.add(profile); | 
 | 6221 |  | 
| Eric Laurent | 1afeecb | 2014-05-14 08:52:28 -0700 | [diff] [blame] | 6222 |     profile = new IOProfile(String8("primary"), AUDIO_PORT_ROLE_SINK, module); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6223 |     profile->mSamplingRates.add(8000); | 
 | 6224 |     profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT); | 
 | 6225 |     profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO); | 
| Eric Laurent | 3a4311c | 2014-03-17 12:00:47 -0700 | [diff] [blame] | 6226 |     profile->mSupportedDevices.add(defaultInputDevice); | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6227 |     module->mInputProfiles.add(profile); | 
 | 6228 |  | 
 | 6229 |     mHwModules.add(module); | 
 | 6230 | } | 
 | 6231 |  | 
| Jean-Michel Trivi | 5bd3f38 | 2014-06-13 16:06:54 -0700 | [diff] [blame] | 6232 | audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr) | 
 | 6233 | { | 
 | 6234 |     // flags to stream type mapping | 
 | 6235 |     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) { | 
 | 6236 |         return AUDIO_STREAM_ENFORCED_AUDIBLE; | 
 | 6237 |     } | 
 | 6238 |     if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) { | 
 | 6239 |         return AUDIO_STREAM_BLUETOOTH_SCO; | 
 | 6240 |     } | 
 | 6241 |  | 
 | 6242 |     // usage to stream type mapping | 
 | 6243 |     switch (attr->usage) { | 
 | 6244 |     case AUDIO_USAGE_MEDIA: | 
 | 6245 |     case AUDIO_USAGE_GAME: | 
 | 6246 |     case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: | 
 | 6247 |     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: | 
 | 6248 |         return AUDIO_STREAM_MUSIC; | 
 | 6249 |     case AUDIO_USAGE_ASSISTANCE_SONIFICATION: | 
 | 6250 |         return AUDIO_STREAM_SYSTEM; | 
 | 6251 |     case AUDIO_USAGE_VOICE_COMMUNICATION: | 
 | 6252 |         return AUDIO_STREAM_VOICE_CALL; | 
 | 6253 |  | 
 | 6254 |     case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: | 
 | 6255 |         return AUDIO_STREAM_DTMF; | 
 | 6256 |  | 
 | 6257 |     case AUDIO_USAGE_ALARM: | 
 | 6258 |         return AUDIO_STREAM_ALARM; | 
 | 6259 |     case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: | 
 | 6260 |         return AUDIO_STREAM_RING; | 
 | 6261 |  | 
 | 6262 |     case AUDIO_USAGE_NOTIFICATION: | 
 | 6263 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: | 
 | 6264 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: | 
 | 6265 |     case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: | 
 | 6266 |     case AUDIO_USAGE_NOTIFICATION_EVENT: | 
 | 6267 |         return AUDIO_STREAM_NOTIFICATION; | 
 | 6268 |  | 
 | 6269 |     case AUDIO_USAGE_UNKNOWN: | 
 | 6270 |     default: | 
 | 6271 |         return AUDIO_STREAM_MUSIC; | 
 | 6272 |     } | 
 | 6273 | } | 
| Eric Laurent | e552edb | 2014-03-10 17:42:56 -0700 | [diff] [blame] | 6274 | }; // namespace android |