blob: d2a88316847fc81b07138e109ce103732dffd9be [file] [log] [blame]
Dima Zavinf0121592011-04-19 16:33:12 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
Srikanth Katta2b4e5ae2013-09-20 16:03:49 +05303 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 * Not a Contribution.
Dima Zavinf0121592011-04-19 16:33:12 -07005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#define LOG_TAG "AudioPolicyManagerBase"
Eric Laurent4e57a1d2013-08-30 15:47:52 -070020//#define LOG_NDEBUG 0
Eric Laurent3cdfddf2012-04-30 18:28:24 -070021
22//#define VERY_VERBOSE_LOGGING
23#ifdef VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
28
Jean-Michel Trivi6d3a1152012-09-17 13:40:35 -070029// A device mask for all audio input devices that are considered "virtual" when evaluating
30// active inputs in getActiveInput()
31#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL AUDIO_DEVICE_IN_REMOTE_SUBMIX
Jean-Michel Trividc3bf1a2013-02-04 16:28:31 -080032// A device mask for all audio output devices that are considered "remote" when evaluating
33// active output devices in isStreamActiveRemotely()
34#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
Jean-Michel Trivi6d3a1152012-09-17 13:40:35 -070035
Dima Zavinf0121592011-04-19 16:33:12 -070036#include <utils/Log.h>
37#include <hardware_legacy/AudioPolicyManagerBase.h>
Eric Laurent1c65a492011-06-17 21:51:11 -070038#include <hardware/audio_effect.h>
Eric Laurent08b014d2012-03-07 19:04:55 -080039#include <hardware/audio.h>
Dima Zavinf0121592011-04-19 16:33:12 -070040#include <math.h>
Eric Laurent5ccdf142012-03-20 13:44:51 -070041#include <hardware_legacy/audio_policy_conf.h>
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +010042#include <cutils/properties.h>
Dima Zavinf0121592011-04-19 16:33:12 -070043
Dima Zavine81531e2011-04-19 16:53:42 -070044namespace android_audio_legacy {
Dima Zavinf0121592011-04-19 16:33:12 -070045
46// ----------------------------------------------------------------------------
47// AudioPolicyInterface implementation
48// ----------------------------------------------------------------------------
49
50
Jean-Michel Trivic8101f52012-08-24 11:45:04 -070051status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device,
Dima Zavinf0121592011-04-19 16:33:12 -070052 AudioSystem::device_connection_state state,
53 const char *device_address)
54{
Eric Laurent3cdfddf2012-04-30 18:28:24 -070055 SortedVector <audio_io_handle_t> outputs;
Dima Zavinf0121592011-04-19 16:33:12 -070056
Steve Block6a705182011-10-20 11:56:19 +010057 ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
Dima Zavinf0121592011-04-19 16:33:12 -070058
59 // connect/disconnect only 1 device at a time
Eric Laurented8f62d2012-08-28 14:32:21 -070060 if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
Dima Zavinf0121592011-04-19 16:33:12 -070061
62 if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
Steve Block5efbd422012-01-08 10:18:02 +000063 ALOGE("setDeviceConnectionState() invalid address: %s", device_address);
Dima Zavinf0121592011-04-19 16:33:12 -070064 return BAD_VALUE;
65 }
66
67 // handle output devices
Jean-Michel Trivic8101f52012-08-24 11:45:04 -070068 if (audio_is_output_device(device)) {
Dima Zavinf0121592011-04-19 16:33:12 -070069
Jean-Michel Trivic8101f52012-08-24 11:45:04 -070070 if (!mHasA2dp && audio_is_a2dp_device(device)) {
Jean-Michel Trivi48387b22012-08-20 14:40:08 -070071 ALOGE("setDeviceConnectionState() invalid A2DP device: %x", device);
Dima Zavinf0121592011-04-19 16:33:12 -070072 return BAD_VALUE;
73 }
Jean-Michel Trivic8101f52012-08-24 11:45:04 -070074 if (!mHasUsb && audio_is_usb_device(device)) {
Jean-Michel Trivi48387b22012-08-20 14:40:08 -070075 ALOGE("setDeviceConnectionState() invalid USB audio device: %x", device);
76 return BAD_VALUE;
77 }
78 if (!mHasRemoteSubmix && audio_is_remote_submix_device((audio_devices_t)device)) {
79 ALOGE("setDeviceConnectionState() invalid remote submix audio device: %x", device);
Eric Laurent599a1fc2012-04-06 09:07:07 -070080 return BAD_VALUE;
81 }
Dima Zavinf0121592011-04-19 16:33:12 -070082
Eric Laurentc9525272012-06-21 09:55:49 -070083 // save a copy of the opened output descriptors before any output is opened or closed
84 // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()
85 mPreviousOutputs = mOutputs;
Dima Zavinf0121592011-04-19 16:33:12 -070086 switch (state)
87 {
88 // handle output device connection
89 case AudioSystem::DEVICE_STATE_AVAILABLE:
90 if (mAvailableOutputDevices & device) {
Steve Block64cca042012-01-05 23:27:53 +000091 ALOGW("setDeviceConnectionState() device already connected: %x", device);
Dima Zavinf0121592011-04-19 16:33:12 -070092 return INVALID_OPERATION;
93 }
Steve Block6a705182011-10-20 11:56:19 +010094 ALOGV("setDeviceConnectionState() connecting device %x", device);
Dima Zavinf0121592011-04-19 16:33:12 -070095
Jean-Michel Trivic8101f52012-08-24 11:45:04 -070096 if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -070097 return INVALID_OPERATION;
98 }
99 ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs",
100 outputs.size());
Dima Zavinf0121592011-04-19 16:33:12 -0700101 // register new device as available
Eric Laurentf9a4e2e2012-03-08 13:39:13 -0800102 mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device);
Dima Zavinf0121592011-04-19 16:33:12 -0700103
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700104 if (!outputs.isEmpty()) {
105 String8 paramStr;
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700106 if (mHasA2dp && audio_is_a2dp_device(device)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700107 // handle A2DP device connection
108 AudioParameter param;
109 param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address));
110 paramStr = param.toString();
111 mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
112 mA2dpSuspended = false;
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700113 } else if (audio_is_bluetooth_sco_device(device)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700114 // handle SCO device connection
115 mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700116 } else if (mHasUsb && audio_is_usb_device(device)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700117 // handle USB device connection
118 mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
119 paramStr = mUsbCardAndDevice;
120 }
Jean-Michel Trivi48387b22012-08-20 14:40:08 -0700121 // not currently handling multiple simultaneous submixes: ignoring remote submix
122 // case and address
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700123 if (!paramStr.isEmpty()) {
124 for (size_t i = 0; i < outputs.size(); i++) {
125 mpClientInterface->setParameters(outputs[i], paramStr);
126 }
127 }
Dima Zavinf0121592011-04-19 16:33:12 -0700128 }
129 break;
130 // handle output device disconnection
131 case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
132 if (!(mAvailableOutputDevices & device)) {
Steve Block64cca042012-01-05 23:27:53 +0000133 ALOGW("setDeviceConnectionState() device not connected: %x", device);
Dima Zavinf0121592011-04-19 16:33:12 -0700134 return INVALID_OPERATION;
135 }
136
Steve Block6a705182011-10-20 11:56:19 +0100137 ALOGV("setDeviceConnectionState() disconnecting device %x", device);
Dima Zavinf0121592011-04-19 16:33:12 -0700138 // remove device from available output devices
Eric Laurentf9a4e2e2012-03-08 13:39:13 -0800139 mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);
Dima Zavinf0121592011-04-19 16:33:12 -0700140
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700141 checkOutputsForDevice(device, state, outputs);
142 if (mHasA2dp && audio_is_a2dp_device(device)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700143 // handle A2DP device disconnection
Eric Laurentb4696fc2012-02-17 10:55:44 -0800144 mA2dpDeviceAddress = "";
145 mA2dpSuspended = false;
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700146 } else if (audio_is_bluetooth_sco_device(device)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700147 // handle SCO device disconnection
Eric Laurentb4696fc2012-02-17 10:55:44 -0800148 mScoDeviceAddress = "";
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700149 } else if (mHasUsb && audio_is_usb_device(device)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700150 // handle USB device disconnection
Eric Laurent599a1fc2012-04-06 09:07:07 -0700151 mUsbCardAndDevice = "";
Dima Zavinf0121592011-04-19 16:33:12 -0700152 }
Jean-Michel Trivi48387b22012-08-20 14:40:08 -0700153 // not currently handling multiple simultaneous submixes: ignoring remote submix
154 // case and address
Dima Zavinf0121592011-04-19 16:33:12 -0700155 } break;
156
157 default:
Steve Block5efbd422012-01-08 10:18:02 +0000158 ALOGE("setDeviceConnectionState() invalid state: %x", state);
Dima Zavinf0121592011-04-19 16:33:12 -0700159 return BAD_VALUE;
160 }
161
Dima Zavinf0121592011-04-19 16:33:12 -0700162 checkA2dpSuspend();
163 checkOutputForAllStrategies();
Eric Laurentb4696fc2012-02-17 10:55:44 -0800164 // outputs must be closed after checkOutputForAllStrategies() is executed
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700165 if (!outputs.isEmpty()) {
166 for (size_t i = 0; i < outputs.size(); i++) {
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100167 AudioOutputDescriptor *desc = mOutputs.valueFor(outputs[i]);
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700168 // close unused outputs after device disconnection or direct outputs that have been
169 // opened by checkOutputsForDevice() to query dynamic parameters
170 if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) ||
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100171 (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
172 (desc->mDirectOpenCount == 0))) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700173 closeOutput(outputs[i]);
174 }
175 }
Dima Zavinf0121592011-04-19 16:33:12 -0700176 }
Eric Laurent5ccdf142012-03-20 13:44:51 -0700177
Eric Laurentc9525272012-06-21 09:55:49 -0700178 updateDevicesAndOutputs();
Eric Laurent5ccdf142012-03-20 13:44:51 -0700179 for (size_t i = 0; i < mOutputs.size(); i++) {
Eric Laurent2c72e9f2012-10-30 16:14:04 -0700180 // do not force device change on duplicated output because if device is 0, it will
181 // also force a device 0 for the two outputs it is duplicated to which may override
182 // a valid device selection on those outputs.
Eric Laurent76e97d32012-09-26 18:50:09 -0700183 setOutputDevice(mOutputs.keyAt(i),
184 getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),
Eric Laurent2c72e9f2012-10-30 16:14:04 -0700185 !mOutputs.valueAt(i)->isDuplicated(),
Eric Laurent76e97d32012-09-26 18:50:09 -0700186 0);
Eric Laurent5ccdf142012-03-20 13:44:51 -0700187 }
Dima Zavinf0121592011-04-19 16:33:12 -0700188
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700189 if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET) {
190 device = AUDIO_DEVICE_IN_WIRED_HEADSET;
191 } else if (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO ||
192 device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
193 device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
194 device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
Dima Zavinf0121592011-04-19 16:33:12 -0700195 } else {
196 return NO_ERROR;
197 }
198 }
199 // handle input devices
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700200 if (audio_is_input_device(device)) {
Dima Zavinf0121592011-04-19 16:33:12 -0700201
202 switch (state)
203 {
204 // handle input device connection
205 case AudioSystem::DEVICE_STATE_AVAILABLE: {
206 if (mAvailableInputDevices & device) {
Steve Block64cca042012-01-05 23:27:53 +0000207 ALOGW("setDeviceConnectionState() device already connected: %d", device);
Dima Zavinf0121592011-04-19 16:33:12 -0700208 return INVALID_OPERATION;
209 }
Eric Laurented8f62d2012-08-28 14:32:21 -0700210 mAvailableInputDevices = mAvailableInputDevices | (device & ~AUDIO_DEVICE_BIT_IN);
Dima Zavinf0121592011-04-19 16:33:12 -0700211 }
212 break;
213
214 // handle input device disconnection
215 case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
216 if (!(mAvailableInputDevices & device)) {
Steve Block64cca042012-01-05 23:27:53 +0000217 ALOGW("setDeviceConnectionState() device not connected: %d", device);
Dima Zavinf0121592011-04-19 16:33:12 -0700218 return INVALID_OPERATION;
219 }
Eric Laurent5ccdf142012-03-20 13:44:51 -0700220 mAvailableInputDevices = (audio_devices_t) (mAvailableInputDevices & ~device);
Dima Zavinf0121592011-04-19 16:33:12 -0700221 } break;
222
223 default:
Steve Block5efbd422012-01-08 10:18:02 +0000224 ALOGE("setDeviceConnectionState() invalid state: %x", state);
Dima Zavinf0121592011-04-19 16:33:12 -0700225 return BAD_VALUE;
226 }
227
228 audio_io_handle_t activeInput = getActiveInput();
229 if (activeInput != 0) {
230 AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
Eric Laurentf9a4e2e2012-03-08 13:39:13 -0800231 audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
Eric Laurented8f62d2012-08-28 14:32:21 -0700232 if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
Steve Block6a705182011-10-20 11:56:19 +0100233 ALOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
Dima Zavinf0121592011-04-19 16:33:12 -0700234 inputDesc->mDevice, newDevice, activeInput);
235 inputDesc->mDevice = newDevice;
236 AudioParameter param = AudioParameter();
237 param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
238 mpClientInterface->setParameters(activeInput, param.toString());
239 }
240 }
241
242 return NO_ERROR;
243 }
244
Steve Block64cca042012-01-05 23:27:53 +0000245 ALOGW("setDeviceConnectionState() invalid device: %x", device);
Dima Zavinf0121592011-04-19 16:33:12 -0700246 return BAD_VALUE;
247}
248
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700249AudioSystem::device_connection_state AudioPolicyManagerBase::getDeviceConnectionState(audio_devices_t device,
Dima Zavinf0121592011-04-19 16:33:12 -0700250 const char *device_address)
251{
252 AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
253 String8 address = String8(device_address);
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700254 if (audio_is_output_device(device)) {
Dima Zavinf0121592011-04-19 16:33:12 -0700255 if (device & mAvailableOutputDevices) {
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700256 if (audio_is_a2dp_device(device) &&
Eric Laurent5ccdf142012-03-20 13:44:51 -0700257 (!mHasA2dp || (address != "" && mA2dpDeviceAddress != address))) {
Dima Zavinf0121592011-04-19 16:33:12 -0700258 return state;
259 }
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700260 if (audio_is_bluetooth_sco_device(device) &&
Dima Zavinf0121592011-04-19 16:33:12 -0700261 address != "" && mScoDeviceAddress != address) {
262 return state;
263 }
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700264 if (audio_is_usb_device(device) &&
Eric Laurent599a1fc2012-04-06 09:07:07 -0700265 (!mHasUsb || (address != "" && mUsbCardAndDevice != address))) {
Jean-Michel Trivi48387b22012-08-20 14:40:08 -0700266 ALOGE("getDeviceConnectionState() invalid device: %x", device);
267 return state;
268 }
269 if (audio_is_remote_submix_device((audio_devices_t)device) && !mHasRemoteSubmix) {
Eric Laurent599a1fc2012-04-06 09:07:07 -0700270 return state;
271 }
Dima Zavinf0121592011-04-19 16:33:12 -0700272 state = AudioSystem::DEVICE_STATE_AVAILABLE;
273 }
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700274 } else if (audio_is_input_device(device)) {
Dima Zavinf0121592011-04-19 16:33:12 -0700275 if (device & mAvailableInputDevices) {
276 state = AudioSystem::DEVICE_STATE_AVAILABLE;
277 }
278 }
279
280 return state;
281}
282
283void AudioPolicyManagerBase::setPhoneState(int state)
284{
Steve Block6a705182011-10-20 11:56:19 +0100285 ALOGV("setPhoneState() state %d", state);
Eric Laurented8f62d2012-08-28 14:32:21 -0700286 audio_devices_t newDevice = AUDIO_DEVICE_NONE;
Dima Zavinf0121592011-04-19 16:33:12 -0700287 if (state < 0 || state >= AudioSystem::NUM_MODES) {
Steve Block64cca042012-01-05 23:27:53 +0000288 ALOGW("setPhoneState() invalid state %d", state);
Dima Zavinf0121592011-04-19 16:33:12 -0700289 return;
290 }
291
292 if (state == mPhoneState ) {
Steve Block64cca042012-01-05 23:27:53 +0000293 ALOGW("setPhoneState() setting same state %d", state);
Dima Zavinf0121592011-04-19 16:33:12 -0700294 return;
295 }
296
297 // if leaving call state, handle special case of active streams
298 // pertaining to sonification strategy see handleIncallSonification()
299 if (isInCall()) {
Steve Block6a705182011-10-20 11:56:19 +0100300 ALOGV("setPhoneState() in call state management: new state is %d", state);
Dima Zavinf0121592011-04-19 16:33:12 -0700301 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
302 handleIncallSonification(stream, false, true);
303 }
304 }
305
306 // store previous phone state for management of sonification strategy below
307 int oldState = mPhoneState;
308 mPhoneState = state;
309 bool force = false;
310
311 // are we entering or starting a call
312 if (!isStateInCall(oldState) && isStateInCall(state)) {
Steve Block6a705182011-10-20 11:56:19 +0100313 ALOGV(" Entering call in setPhoneState()");
Dima Zavinf0121592011-04-19 16:33:12 -0700314 // force routing command to audio hardware when starting a call
315 // even if no device change is needed
316 force = true;
Eric Laurent87e28f72013-10-03 18:02:16 -0700317 for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
318 mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
319 sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j];
320 }
Dima Zavinf0121592011-04-19 16:33:12 -0700321 } else if (isStateInCall(oldState) && !isStateInCall(state)) {
Steve Block6a705182011-10-20 11:56:19 +0100322 ALOGV(" Exiting call in setPhoneState()");
Dima Zavinf0121592011-04-19 16:33:12 -0700323 // force routing command to audio hardware when exiting a call
324 // even if no device change is needed
325 force = true;
Eric Laurent87e28f72013-10-03 18:02:16 -0700326 for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
327 mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
328 sVolumeProfiles[AUDIO_STREAM_DTMF][j];
329 }
Dima Zavinf0121592011-04-19 16:33:12 -0700330 } else if (isStateInCall(state) && (state != oldState)) {
Steve Block6a705182011-10-20 11:56:19 +0100331 ALOGV(" Switching between telephony and VoIP in setPhoneState()");
Dima Zavinf0121592011-04-19 16:33:12 -0700332 // force routing command to audio hardware when switching between telephony and VoIP
333 // even if no device change is needed
334 force = true;
335 }
336
337 // check for device and output changes triggered by new phone state
Eric Laurent5ccdf142012-03-20 13:44:51 -0700338 newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/);
Dima Zavinf0121592011-04-19 16:33:12 -0700339 checkA2dpSuspend();
340 checkOutputForAllStrategies();
Eric Laurentc9525272012-06-21 09:55:49 -0700341 updateDevicesAndOutputs();
Dima Zavinf0121592011-04-19 16:33:12 -0700342
Eric Laurentb4696fc2012-02-17 10:55:44 -0800343 AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
Dima Zavinf0121592011-04-19 16:33:12 -0700344
345 // force routing command to audio hardware when ending call
346 // even if no device change is needed
Eric Laurented8f62d2012-08-28 14:32:21 -0700347 if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) {
Dima Zavinf0121592011-04-19 16:33:12 -0700348 newDevice = hwOutputDesc->device();
349 }
350
Dima Zavinf0121592011-04-19 16:33:12 -0700351 int delayMs = 0;
SathishKumar Mani77268632012-10-10 18:58:40 -0700352 if (isStateInCall(state)) {
Eric Laurent80f5b042013-03-25 09:58:09 -0700353 nsecs_t sysTime = systemTime();
SathishKumar Mani77268632012-10-10 18:58:40 -0700354 for (size_t i = 0; i < mOutputs.size(); i++) {
355 AudioOutputDescriptor *desc = mOutputs.valueAt(i);
Eric Laurent80f5b042013-03-25 09:58:09 -0700356 // mute media and sonification strategies and delay device switch by the largest
357 // latency of any output where either strategy is active.
358 // This avoid sending the ring tone or music tail into the earpiece or headset.
359 if ((desc->isStrategyActive(STRATEGY_MEDIA,
360 SONIFICATION_HEADSET_MUSIC_DELAY,
361 sysTime) ||
362 desc->isStrategyActive(STRATEGY_SONIFICATION,
363 SONIFICATION_HEADSET_MUSIC_DELAY,
364 sysTime)) &&
365 (delayMs < (int)desc->mLatency*2)) {
366 delayMs = desc->mLatency*2;
SathishKumar Mani77268632012-10-10 18:58:40 -0700367 }
Eric Laurent80f5b042013-03-25 09:58:09 -0700368 setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i));
369 setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS,
370 getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/));
371 setStrategyMute(STRATEGY_SONIFICATION, true, mOutputs.keyAt(i));
372 setStrategyMute(STRATEGY_SONIFICATION, false, mOutputs.keyAt(i), MUTE_TIME_MS,
373 getDeviceForStrategy(STRATEGY_SONIFICATION, true /*fromCache*/));
SathishKumar Mani77268632012-10-10 18:58:40 -0700374 }
375 }
376
Dima Zavinf0121592011-04-19 16:33:12 -0700377 // change routing is necessary
Eric Laurentb4696fc2012-02-17 10:55:44 -0800378 setOutputDevice(mPrimaryOutput, newDevice, force, delayMs);
Dima Zavinf0121592011-04-19 16:33:12 -0700379
380 // if entering in call state, handle special case of active streams
381 // pertaining to sonification strategy see handleIncallSonification()
382 if (isStateInCall(state)) {
Steve Block6a705182011-10-20 11:56:19 +0100383 ALOGV("setPhoneState() in call state management: new state is %d", state);
Dima Zavinf0121592011-04-19 16:33:12 -0700384 for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
385 handleIncallSonification(stream, true, true);
386 }
387 }
388
389 // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
390 if (state == AudioSystem::MODE_RINGTONE &&
391 isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) {
392 mLimitRingtoneVolume = true;
393 } else {
394 mLimitRingtoneVolume = false;
395 }
396}
397
Dima Zavinf0121592011-04-19 16:33:12 -0700398void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
399{
Steve Block6a705182011-10-20 11:56:19 +0100400 ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
Dima Zavinf0121592011-04-19 16:33:12 -0700401
402 bool forceVolumeReeval = false;
403 switch(usage) {
404 case AudioSystem::FOR_COMMUNICATION:
405 if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
406 config != AudioSystem::FORCE_NONE) {
Steve Block64cca042012-01-05 23:27:53 +0000407 ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
Dima Zavinf0121592011-04-19 16:33:12 -0700408 return;
409 }
410 forceVolumeReeval = true;
411 mForceUse[usage] = config;
412 break;
413 case AudioSystem::FOR_MEDIA:
414 if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
415 config != AudioSystem::FORCE_WIRED_ACCESSORY &&
416 config != AudioSystem::FORCE_ANALOG_DOCK &&
Eric Laurent1afd84f2012-05-21 08:50:50 -0700417 config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE &&
Jean-Michel Trivi31363a92012-10-11 18:06:33 -0700418 config != AudioSystem::FORCE_NO_BT_A2DP) {
Steve Block64cca042012-01-05 23:27:53 +0000419 ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
Dima Zavinf0121592011-04-19 16:33:12 -0700420 return;
421 }
422 mForceUse[usage] = config;
423 break;
424 case AudioSystem::FOR_RECORD:
425 if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
426 config != AudioSystem::FORCE_NONE) {
Steve Block64cca042012-01-05 23:27:53 +0000427 ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
Dima Zavinf0121592011-04-19 16:33:12 -0700428 return;
429 }
430 mForceUse[usage] = config;
431 break;
432 case AudioSystem::FOR_DOCK:
433 if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
434 config != AudioSystem::FORCE_BT_DESK_DOCK &&
435 config != AudioSystem::FORCE_WIRED_ACCESSORY &&
436 config != AudioSystem::FORCE_ANALOG_DOCK &&
437 config != AudioSystem::FORCE_DIGITAL_DOCK) {
Steve Block64cca042012-01-05 23:27:53 +0000438 ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
Dima Zavinf0121592011-04-19 16:33:12 -0700439 }
440 forceVolumeReeval = true;
441 mForceUse[usage] = config;
442 break;
Eric Laurent738207d2012-10-08 15:53:09 -0700443 case AudioSystem::FOR_SYSTEM:
444 if (config != AudioSystem::FORCE_NONE &&
445 config != AudioSystem::FORCE_SYSTEM_ENFORCED) {
446 ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
447 }
448 forceVolumeReeval = true;
449 mForceUse[usage] = config;
450 break;
Dima Zavinf0121592011-04-19 16:33:12 -0700451 default:
Steve Block64cca042012-01-05 23:27:53 +0000452 ALOGW("setForceUse() invalid usage %d", usage);
Dima Zavinf0121592011-04-19 16:33:12 -0700453 break;
454 }
455
Eric Laurent5ccdf142012-03-20 13:44:51 -0700456 // check for device and output changes triggered by new force usage
Dima Zavinf0121592011-04-19 16:33:12 -0700457 checkA2dpSuspend();
458 checkOutputForAllStrategies();
Eric Laurentc9525272012-06-21 09:55:49 -0700459 updateDevicesAndOutputs();
Eric Laurent5ccdf142012-03-20 13:44:51 -0700460 for (size_t i = 0; i < mOutputs.size(); i++) {
461 audio_io_handle_t output = mOutputs.keyAt(i);
462 audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/);
Eric Laurented8f62d2012-08-28 14:32:21 -0700463 setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
464 if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
Eric Laurent5ccdf142012-03-20 13:44:51 -0700465 applyStreamVolumes(output, newDevice, 0, true);
466 }
Dima Zavinf0121592011-04-19 16:33:12 -0700467 }
468
469 audio_io_handle_t activeInput = getActiveInput();
470 if (activeInput != 0) {
471 AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
Eric Laurent5ccdf142012-03-20 13:44:51 -0700472 audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
Eric Laurented8f62d2012-08-28 14:32:21 -0700473 if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
Steve Block6a705182011-10-20 11:56:19 +0100474 ALOGV("setForceUse() changing device from %x to %x for input %d",
Dima Zavinf0121592011-04-19 16:33:12 -0700475 inputDesc->mDevice, newDevice, activeInput);
476 inputDesc->mDevice = newDevice;
477 AudioParameter param = AudioParameter();
478 param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
479 mpClientInterface->setParameters(activeInput, param.toString());
480 }
481 }
482
483}
484
485AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage)
486{
487 return mForceUse[usage];
488}
489
490void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* value)
491{
Steve Block6a705182011-10-20 11:56:19 +0100492 ALOGV("setSystemProperty() property %s, value %s", property, value);
Dima Zavinf0121592011-04-19 16:33:12 -0700493}
494
Eric Laurentb40b96a2013-10-06 12:39:32 -0700495// Find a direct output profile compatible with the parameters passed, even if the input flags do
496// not explicitly request a direct output
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700497AudioPolicyManagerBase::IOProfile *AudioPolicyManagerBase::getProfileForDirectOutput(
498 audio_devices_t device,
Eric Laurent70c236c2012-03-28 11:27:13 -0700499 uint32_t samplingRate,
500 uint32_t format,
501 uint32_t channelMask,
Eric Laurent0977cf52012-04-18 09:28:52 -0700502 audio_output_flags_t flags)
Eric Laurent70c236c2012-03-28 11:27:13 -0700503{
504 for (size_t i = 0; i < mHwModules.size(); i++) {
505 if (mHwModules[i]->mHandle == 0) {
506 continue;
507 }
508 for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) {
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100509 IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
510 if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
511 if (profile->isCompatibleProfile(device, samplingRate, format,
512 channelMask,
513 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
514 if (mAvailableOutputDevices & profile->mSupportedDevices) {
515 return mHwModules[i]->mOutputProfiles[j];
516 }
517 }
Eric Laurentb40b96a2013-10-06 12:39:32 -0700518 } else {
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100519 if (profile->isCompatibleProfile(device, samplingRate, format,
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700520 channelMask,
Shiv Maliyappanahallif56f9772013-10-31 15:32:45 -0700521 (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_DIRECT | flags))) {
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100522 if (mAvailableOutputDevices & profile->mSupportedDevices) {
523 return mHwModules[i]->mOutputProfiles[j];
524 }
525 }
526 }
Eric Laurent70c236c2012-03-28 11:27:13 -0700527 }
528 }
529 return 0;
530}
531
Dima Zavinf0121592011-04-19 16:33:12 -0700532audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
533 uint32_t samplingRate,
534 uint32_t format,
Eric Laurent70c236c2012-03-28 11:27:13 -0700535 uint32_t channelMask,
Richard Fitzgeraldb4d07b92013-03-25 16:18:26 +0000536 AudioSystem::output_flags flags,
537 const audio_offload_info_t *offloadInfo)
Dima Zavinf0121592011-04-19 16:33:12 -0700538{
539 audio_io_handle_t output = 0;
540 uint32_t latency = 0;
541 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
Eric Laurent5ccdf142012-03-20 13:44:51 -0700542 audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
Shiv Maliyappanahalli92ace722013-11-07 18:48:47 -0800543 IOProfile *profile = NULL;
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100544 ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
545 device, stream, samplingRate, format, channelMask, flags);
Dima Zavinf0121592011-04-19 16:33:12 -0700546
547#ifdef AUDIO_POLICY_TEST
548 if (mCurOutput != 0) {
Eric Laurent70c236c2012-03-28 11:27:13 -0700549 ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d",
Dima Zavinf0121592011-04-19 16:33:12 -0700550 mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);
551
552 if (mTestOutputs[mCurOutput] == 0) {
Steve Block6a705182011-10-20 11:56:19 +0100553 ALOGV("getOutput() opening test output");
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700554 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(NULL);
Dima Zavinf0121592011-04-19 16:33:12 -0700555 outputDesc->mDevice = mTestDevice;
556 outputDesc->mSamplingRate = mTestSamplingRate;
557 outputDesc->mFormat = mTestFormat;
Eric Laurent70c236c2012-03-28 11:27:13 -0700558 outputDesc->mChannelMask = mTestChannels;
Dima Zavinf0121592011-04-19 16:33:12 -0700559 outputDesc->mLatency = mTestLatencyMs;
Eric Laurent0977cf52012-04-18 09:28:52 -0700560 outputDesc->mFlags = (audio_output_flags_t)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
Dima Zavinf0121592011-04-19 16:33:12 -0700561 outputDesc->mRefCount[stream] = 0;
Eric Laurent70c236c2012-03-28 11:27:13 -0700562 mTestOutputs[mCurOutput] = mpClientInterface->openOutput(0, &outputDesc->mDevice,
Dima Zavinf0121592011-04-19 16:33:12 -0700563 &outputDesc->mSamplingRate,
564 &outputDesc->mFormat,
Eric Laurent70c236c2012-03-28 11:27:13 -0700565 &outputDesc->mChannelMask,
Dima Zavinf0121592011-04-19 16:33:12 -0700566 &outputDesc->mLatency,
Richard Fitzgeraldb4d07b92013-03-25 16:18:26 +0000567 outputDesc->mFlags,
568 offloadInfo);
Dima Zavinf0121592011-04-19 16:33:12 -0700569 if (mTestOutputs[mCurOutput]) {
570 AudioParameter outputCmd = AudioParameter();
571 outputCmd.addInt(String8("set_id"),mCurOutput);
572 mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
573 addOutput(mTestOutputs[mCurOutput], outputDesc);
574 }
575 }
576 return mTestOutputs[mCurOutput];
577 }
578#endif //AUDIO_POLICY_TEST
579
580 // open a direct output if required by specified parameters
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100581 //force direct flag if offload flag is set: offloading implies a direct output stream
582 // and all common behaviors are driven by checking only the direct flag
583 // this should normally be set appropriately in the policy configuration file
584 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
585 flags = (AudioSystem::output_flags)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
586 }
587
Mingming Yin689f85d2013-11-22 12:00:25 -0800588#ifdef QCOM_HARDWARE
589 if ((format == AudioSystem::PCM_16_BIT) &&(AudioSystem::popCount(channelMask) > 2)) {
590 ALOGV("owerwrite flag(%x) for PCM16 multi-channel(CM:%x) playback", flags ,channelMask);
591 flags = (AudioSystem::output_flags)AUDIO_OUTPUT_FLAG_DIRECT;
592 }
593#endif
594
Eric Laurent000bb512013-10-12 16:29:39 -0700595 // Do not allow offloading if one non offloadable effect is enabled. This prevents from
596 // creating an offloaded track and tearing it down immediately after start when audioflinger
597 // detects there is an active non offloadable effect.
598 // FIXME: We should check the audio session here but we do not have it in this context.
599 // This may prevent offloading in rare situations where effects are left active by apps
600 // in the background.
Steve Kondik5b7b6362013-12-27 17:07:28 -0800601 if ((((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
602 !isNonOffloadableEffectEnabled()) &&
603 flags & AUDIO_OUTPUT_FLAG_DIRECT) {
Shiv Maliyappanahalli92ace722013-11-07 18:48:47 -0800604 profile = getProfileForDirectOutput(device,
Eric Laurent000bb512013-10-12 16:29:39 -0700605 samplingRate,
606 format,
607 channelMask,
608 (audio_output_flags_t)flags);
Shiv Maliyappanahalli92ace722013-11-07 18:48:47 -0800609 }
610
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700611 if (profile != NULL) {
Eric Laurent5a950c92013-04-03 17:31:04 -0700612 AudioOutputDescriptor *outputDesc = NULL;
Dima Zavinf0121592011-04-19 16:33:12 -0700613
Eric Laurent5a950c92013-04-03 17:31:04 -0700614 for (size_t i = 0; i < mOutputs.size(); i++) {
615 AudioOutputDescriptor *desc = mOutputs.valueAt(i);
616 if (!desc->isDuplicated() && (profile == desc->mProfile)) {
617 outputDesc = desc;
618 // reuse direct output if currently open and configured with same parameters
619 if ((samplingRate == outputDesc->mSamplingRate) &&
620 (format == outputDesc->mFormat) &&
621 (channelMask == outputDesc->mChannelMask)) {
622 outputDesc->mDirectOpenCount++;
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100623 ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
Eric Laurent5a950c92013-04-03 17:31:04 -0700624 return mOutputs.keyAt(i);
625 }
626 }
627 }
628 // close direct output if currently open and configured with different parameters
629 if (outputDesc != NULL) {
630 closeOutput(outputDesc->mId);
631 }
632 outputDesc = new AudioOutputDescriptor(profile);
Dima Zavinf0121592011-04-19 16:33:12 -0700633 outputDesc->mDevice = device;
634 outputDesc->mSamplingRate = samplingRate;
Eric Laurent70c236c2012-03-28 11:27:13 -0700635 outputDesc->mFormat = (audio_format_t)format;
636 outputDesc->mChannelMask = (audio_channel_mask_t)channelMask;
Dima Zavinf0121592011-04-19 16:33:12 -0700637 outputDesc->mLatency = 0;
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100638 outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags);
Dima Zavinf0121592011-04-19 16:33:12 -0700639 outputDesc->mRefCount[stream] = 0;
640 outputDesc->mStopTime[stream] = 0;
Eric Laurent5a950c92013-04-03 17:31:04 -0700641 outputDesc->mDirectOpenCount = 1;
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700642 output = mpClientInterface->openOutput(profile->mModule->mHandle,
Eric Laurent70c236c2012-03-28 11:27:13 -0700643 &outputDesc->mDevice,
Dima Zavinf0121592011-04-19 16:33:12 -0700644 &outputDesc->mSamplingRate,
645 &outputDesc->mFormat,
Eric Laurent70c236c2012-03-28 11:27:13 -0700646 &outputDesc->mChannelMask,
Dima Zavinf0121592011-04-19 16:33:12 -0700647 &outputDesc->mLatency,
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100648 outputDesc->mFlags,
649 offloadInfo);
Dima Zavinf0121592011-04-19 16:33:12 -0700650
Jean-Michel Trivi9f1f9b52012-04-05 11:44:49 -0700651 // only accept an output with the requested parameters
Dima Zavinf0121592011-04-19 16:33:12 -0700652 if (output == 0 ||
653 (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) ||
654 (format != 0 && format != outputDesc->mFormat) ||
Eric Laurent70c236c2012-03-28 11:27:13 -0700655 (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700656 ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d,"
657 "format %d %d, channelMask %04x %04x", output, samplingRate,
658 outputDesc->mSamplingRate, format, outputDesc->mFormat, channelMask,
659 outputDesc->mChannelMask);
Dima Zavinf0121592011-04-19 16:33:12 -0700660 if (output != 0) {
661 mpClientInterface->closeOutput(output);
662 }
663 delete outputDesc;
664 return 0;
665 }
Eric Laurent45c76392013-09-12 17:39:21 -0700666 audio_io_handle_t srcOutput = getOutputForEffect();
Dima Zavinf0121592011-04-19 16:33:12 -0700667 addOutput(output, outputDesc);
Eric Laurent45c76392013-09-12 17:39:21 -0700668 audio_io_handle_t dstOutput = getOutputForEffect();
669 if (dstOutput == output) {
670 mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput);
671 }
Eric Laurent5a950c92013-04-03 17:31:04 -0700672 mPreviousOutputs = mOutputs;
673 ALOGV("getOutput() returns new direct output %d", output);
Dima Zavinf0121592011-04-19 16:33:12 -0700674 return output;
675 }
676
Jean-Michel Trivi9f1f9b52012-04-05 11:44:49 -0700677 // ignoring channel mask due to downmix capability in mixer
678
Dima Zavinf0121592011-04-19 16:33:12 -0700679 // open a non direct output
680
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100681 // for non direct outputs, only PCM is supported
682 if (audio_is_linear_pcm((audio_format_t)format)) {
683 // get which output is suitable for the specified stream. The actual
684 // routing change will happen when startOutput() will be called
685 SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
Dima Zavinf0121592011-04-19 16:33:12 -0700686
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100687 output = selectOutput(outputs, flags);
688 }
689 ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d,"
Eric Laurent70c236c2012-03-28 11:27:13 -0700690 "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags);
Dima Zavinf0121592011-04-19 16:33:12 -0700691
Eric Laurent5ccdf142012-03-20 13:44:51 -0700692 ALOGV("getOutput() returns output %d", output);
693
Dima Zavinf0121592011-04-19 16:33:12 -0700694 return output;
695}
696
Eric Laurent5ccdf142012-03-20 13:44:51 -0700697audio_io_handle_t AudioPolicyManagerBase::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
698 AudioSystem::output_flags flags)
699{
700 // select one output among several that provide a path to a particular device or set of
701 // devices (the list was previously build by getOutputsForDevice()).
702 // The priority is as follows:
703 // 1: the output with the highest number of requested policy flags
704 // 2: the primary output
705 // 3: the first output in the list
706
707 if (outputs.size() == 0) {
708 return 0;
709 }
710 if (outputs.size() == 1) {
711 return outputs[0];
712 }
713
714 int maxCommonFlags = 0;
715 audio_io_handle_t outputFlags = 0;
716 audio_io_handle_t outputPrimary = 0;
717
718 for (size_t i = 0; i < outputs.size(); i++) {
719 AudioOutputDescriptor *outputDesc = mOutputs.valueFor(outputs[i]);
720 if (!outputDesc->isDuplicated()) {
721 int commonFlags = (int)AudioSystem::popCount(outputDesc->mProfile->mFlags & flags);
722 if (commonFlags > maxCommonFlags) {
723 outputFlags = outputs[i];
724 maxCommonFlags = commonFlags;
725 ALOGV("selectOutput() commonFlags for output %d, %04x", outputs[i], commonFlags);
726 }
Eric Laurent0977cf52012-04-18 09:28:52 -0700727 if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Eric Laurent5ccdf142012-03-20 13:44:51 -0700728 outputPrimary = outputs[i];
729 }
730 }
731 }
732
733 if (outputFlags != 0) {
734 return outputFlags;
735 }
736 if (outputPrimary != 0) {
737 return outputPrimary;
738 }
739
740 return outputs[0];
741}
742
Dima Zavinf0121592011-04-19 16:33:12 -0700743status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
744 AudioSystem::stream_type stream,
745 int session)
746{
Steve Block6a705182011-10-20 11:56:19 +0100747 ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
Dima Zavinf0121592011-04-19 16:33:12 -0700748 ssize_t index = mOutputs.indexOfKey(output);
749 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +0000750 ALOGW("startOutput() unknow output %d", output);
Dima Zavinf0121592011-04-19 16:33:12 -0700751 return BAD_VALUE;
752 }
753
754 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
Dima Zavinf0121592011-04-19 16:33:12 -0700755
Eric Laurent5ccdf142012-03-20 13:44:51 -0700756 // increment usage count for this stream on the requested output:
Dima Zavinf0121592011-04-19 16:33:12 -0700757 // NOTE that the usage count is the same for duplicated output and hardware output which is
Eric Laurent5ccdf142012-03-20 13:44:51 -0700758 // necessary for a correct control of hardware output routing by startOutput() and stopOutput()
Dima Zavinf0121592011-04-19 16:33:12 -0700759 outputDesc->changeRefCount(stream, 1);
760
Eric Laurent5ccdf142012-03-20 13:44:51 -0700761 if (outputDesc->mRefCount[stream] == 1) {
Eric Laurent5ccdf142012-03-20 13:44:51 -0700762 audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/);
Eric Laurentb2971bf2012-04-13 18:48:06 -0700763 routing_strategy strategy = getStrategy(stream);
764 bool shouldWait = (strategy == STRATEGY_SONIFICATION) ||
765 (strategy == STRATEGY_SONIFICATION_RESPECTFUL);
766 uint32_t waitMs = 0;
Eric Laurent5ccdf142012-03-20 13:44:51 -0700767 bool force = false;
768 for (size_t i = 0; i < mOutputs.size(); i++) {
769 AudioOutputDescriptor *desc = mOutputs.valueAt(i);
Eric Laurentb2971bf2012-04-13 18:48:06 -0700770 if (desc != outputDesc) {
771 // force a device change if any other output is managed by the same hw
772 // module and has a current device selection that differs from selected device.
773 // In this case, the audio HAL must receive the new device selection so that it can
774 // change the device currently selected by the other active output.
775 if (outputDesc->sharesHwModuleWith(desc) &&
Eric Laurent5ccdf142012-03-20 13:44:51 -0700776 desc->device() != newDevice) {
Eric Laurentb2971bf2012-04-13 18:48:06 -0700777 force = true;
778 }
779 // wait for audio on other active outputs to be presented when starting
780 // a notification so that audio focus effect can propagate.
Eric Laurent42fa8212012-11-07 12:09:54 -0800781 uint32_t latency = desc->latency();
782 if (shouldWait && desc->isActive(latency * 2) && (waitMs < latency)) {
783 waitMs = latency;
Eric Laurentb2971bf2012-04-13 18:48:06 -0700784 }
Eric Laurent5ccdf142012-03-20 13:44:51 -0700785 }
786 }
Eric Laurentb2971bf2012-04-13 18:48:06 -0700787 uint32_t muteWaitMs = setOutputDevice(output, newDevice, force);
Eric Laurent5ccdf142012-03-20 13:44:51 -0700788
789 // handle special case for sonification while in call
790 if (isInCall()) {
791 handleIncallSonification(stream, true, false);
792 }
793
794 // apply volume rules for current stream and device if necessary
795 checkAndSetVolume(stream,
Jean-Michel Trivic8101f52012-08-24 11:45:04 -0700796 mStreams[stream].getVolumeIndex(newDevice),
Eric Laurent5ccdf142012-03-20 13:44:51 -0700797 output,
798 newDevice);
799
800 // update the outputs if starting an output with a stream that can affect notification
801 // routing
802 handleNotificationRoutingForStream(stream);
Eric Laurentb2971bf2012-04-13 18:48:06 -0700803 if (waitMs > muteWaitMs) {
804 usleep((waitMs - muteWaitMs) * 2 * 1000);
805 }
Dima Zavinf0121592011-04-19 16:33:12 -0700806 }
Dima Zavinf0121592011-04-19 16:33:12 -0700807 return NO_ERROR;
808}
809
Eric Laurent5ccdf142012-03-20 13:44:51 -0700810
Dima Zavinf0121592011-04-19 16:33:12 -0700811status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
812 AudioSystem::stream_type stream,
813 int session)
814{
Steve Block6a705182011-10-20 11:56:19 +0100815 ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
Dima Zavinf0121592011-04-19 16:33:12 -0700816 ssize_t index = mOutputs.indexOfKey(output);
817 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +0000818 ALOGW("stopOutput() unknow output %d", output);
Dima Zavinf0121592011-04-19 16:33:12 -0700819 return BAD_VALUE;
820 }
821
822 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
Dima Zavinf0121592011-04-19 16:33:12 -0700823
Steve Kondik41083412014-05-07 15:13:51 -0700824 // handle special case for sonification while in call
825 if (isInCall()) {
826 handleIncallSonification(stream, false, false);
827 }
Dima Zavinf0121592011-04-19 16:33:12 -0700828
829 if (outputDesc->mRefCount[stream] > 0) {
830 // decrement usage count of this stream on the output
831 outputDesc->changeRefCount(stream, -1);
832 // store time at which the stream was stopped - see isStreamActive()
Eric Laurent5ccdf142012-03-20 13:44:51 -0700833 if (outputDesc->mRefCount[stream] == 0) {
834 outputDesc->mStopTime[stream] = systemTime();
835 audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/);
836 // delay the device switch by twice the latency because stopOutput() is executed when
837 // the track stop() command is received and at that time the audio track buffer can
838 // still contain data that needs to be drained. The latency only covers the audio HAL
839 // and kernel buffers. Also the latency does not always include additional delay in the
840 // audio path (audio DSP, CODEC ...)
841 setOutputDevice(output, newDevice, false, outputDesc->mLatency*2);
Dima Zavinf0121592011-04-19 16:33:12 -0700842
Eric Laurent5ccdf142012-03-20 13:44:51 -0700843 // force restoring the device selection on other active outputs if it differs from the
844 // one being selected for this output
845 for (size_t i = 0; i < mOutputs.size(); i++) {
846 audio_io_handle_t curOutput = mOutputs.keyAt(i);
847 AudioOutputDescriptor *desc = mOutputs.valueAt(i);
848 if (curOutput != output &&
Eric Laurent80f5b042013-03-25 09:58:09 -0700849 desc->isActive() &&
Eric Laurent5ccdf142012-03-20 13:44:51 -0700850 outputDesc->sharesHwModuleWith(desc) &&
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +0100851 (newDevice != desc->device())) {
Eric Laurent5ccdf142012-03-20 13:44:51 -0700852 setOutputDevice(curOutput,
853 getNewDevice(curOutput, false /*fromCache*/),
854 true,
855 outputDesc->mLatency*2);
856 }
857 }
858 // update the outputs if stopping one with a stream that can affect notification routing
859 handleNotificationRoutingForStream(stream);
Dima Zavinf0121592011-04-19 16:33:12 -0700860 }
861 return NO_ERROR;
862 } else {
Steve Block64cca042012-01-05 23:27:53 +0000863 ALOGW("stopOutput() refcount is already 0 for output %d", output);
Dima Zavinf0121592011-04-19 16:33:12 -0700864 return INVALID_OPERATION;
865 }
866}
867
868void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
869{
Steve Block6a705182011-10-20 11:56:19 +0100870 ALOGV("releaseOutput() %d", output);
Dima Zavinf0121592011-04-19 16:33:12 -0700871 ssize_t index = mOutputs.indexOfKey(output);
872 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +0000873 ALOGW("releaseOutput() releasing unknown output %d", output);
Dima Zavinf0121592011-04-19 16:33:12 -0700874 return;
875 }
876
877#ifdef AUDIO_POLICY_TEST
878 int testIndex = testOutputIndex(output);
879 if (testIndex != 0) {
880 AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
Eric Laurent80f5b042013-03-25 09:58:09 -0700881 if (outputDesc->isActive()) {
Dima Zavinf0121592011-04-19 16:33:12 -0700882 mpClientInterface->closeOutput(output);
883 delete mOutputs.valueAt(index);
884 mOutputs.removeItem(output);
885 mTestOutputs[testIndex] = 0;
886 }
887 return;
888 }
889#endif //AUDIO_POLICY_TEST
890
Eric Laurent5a950c92013-04-03 17:31:04 -0700891 AudioOutputDescriptor *desc = mOutputs.valueAt(index);
892 if (desc->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
893 if (desc->mDirectOpenCount <= 0) {
894 ALOGW("releaseOutput() invalid open count %d for output %d",
895 desc->mDirectOpenCount, output);
896 return;
897 }
898 if (--desc->mDirectOpenCount == 0) {
899 closeOutput(output);
Eric Laurent45c76392013-09-12 17:39:21 -0700900 // If effects where present on the output, audioflinger moved them to the primary
901 // output by default: move them back to the appropriate output.
902 audio_io_handle_t dstOutput = getOutputForEffect();
903 if (dstOutput != mPrimaryOutput) {
904 mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput);
905 }
Eric Laurent5a950c92013-04-03 17:31:04 -0700906 }
Dima Zavinf0121592011-04-19 16:33:12 -0700907 }
908}
909
Eric Laurent45c76392013-09-12 17:39:21 -0700910
Dima Zavinf0121592011-04-19 16:33:12 -0700911audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource,
912 uint32_t samplingRate,
913 uint32_t format,
Eric Laurent70c236c2012-03-28 11:27:13 -0700914 uint32_t channelMask,
Dima Zavinf0121592011-04-19 16:33:12 -0700915 AudioSystem::audio_in_acoustics acoustics)
916{
917 audio_io_handle_t input = 0;
Eric Laurentf9a4e2e2012-03-08 13:39:13 -0800918 audio_devices_t device = getDeviceForInputSource(inputSource);
Dima Zavinf0121592011-04-19 16:33:12 -0700919
Eric Laurent70c236c2012-03-28 11:27:13 -0700920 ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x",
921 inputSource, samplingRate, format, channelMask, acoustics);
Dima Zavinf0121592011-04-19 16:33:12 -0700922
Eric Laurented8f62d2012-08-28 14:32:21 -0700923 if (device == AUDIO_DEVICE_NONE) {
Eric Laurent5ccdf142012-03-20 13:44:51 -0700924 ALOGW("getInput() could not find device for inputSource %d", inputSource);
Dima Zavinf0121592011-04-19 16:33:12 -0700925 return 0;
926 }
927
928 // adapt channel selection to input source
929 switch(inputSource) {
930 case AUDIO_SOURCE_VOICE_UPLINK:
Eric Laurent70c236c2012-03-28 11:27:13 -0700931 channelMask = AudioSystem::CHANNEL_IN_VOICE_UPLINK;
Dima Zavinf0121592011-04-19 16:33:12 -0700932 break;
933 case AUDIO_SOURCE_VOICE_DOWNLINK:
Eric Laurent70c236c2012-03-28 11:27:13 -0700934 channelMask = AudioSystem::CHANNEL_IN_VOICE_DNLINK;
Dima Zavinf0121592011-04-19 16:33:12 -0700935 break;
936 case AUDIO_SOURCE_VOICE_CALL:
Eric Laurent70c236c2012-03-28 11:27:13 -0700937 channelMask = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
Dima Zavinf0121592011-04-19 16:33:12 -0700938 break;
939 default:
940 break;
941 }
942
Eric Laurent5ccdf142012-03-20 13:44:51 -0700943 IOProfile *profile = getInputProfile(device,
944 samplingRate,
945 format,
Eric Laurent70c236c2012-03-28 11:27:13 -0700946 channelMask);
Eric Laurent5ccdf142012-03-20 13:44:51 -0700947 if (profile == NULL) {
948 ALOGW("getInput() could not find profile for device %04x, samplingRate %d, format %d,"
Eric Laurent70c236c2012-03-28 11:27:13 -0700949 "channelMask %04x",
950 device, samplingRate, format, channelMask);
951 return 0;
952 }
953
954 if (profile->mModule->mHandle == 0) {
Eric Laurent3cdfddf2012-04-30 18:28:24 -0700955 ALOGE("getInput(): HW module %s not opened", profile->mModule->mName);
Eric Laurent5ccdf142012-03-20 13:44:51 -0700956 return 0;
957 }
958
959 AudioInputDescriptor *inputDesc = new AudioInputDescriptor(profile);
Dima Zavinf0121592011-04-19 16:33:12 -0700960
961 inputDesc->mInputSource = inputSource;
962 inputDesc->mDevice = device;
963 inputDesc->mSamplingRate = samplingRate;
Eric Laurent70c236c2012-03-28 11:27:13 -0700964 inputDesc->mFormat = (audio_format_t)format;
965 inputDesc->mChannelMask = (audio_channel_mask_t)channelMask;
Dima Zavinf0121592011-04-19 16:33:12 -0700966 inputDesc->mRefCount = 0;
Eric Laurent70c236c2012-03-28 11:27:13 -0700967 input = mpClientInterface->openInput(profile->mModule->mHandle,
968 &inputDesc->mDevice,
Dima Zavinf0121592011-04-19 16:33:12 -0700969 &inputDesc->mSamplingRate,
970 &inputDesc->mFormat,
Eric Laurent70c236c2012-03-28 11:27:13 -0700971 &inputDesc->mChannelMask);
Dima Zavinf0121592011-04-19 16:33:12 -0700972
973 // only accept input with the exact requested set of parameters
974 if (input == 0 ||
975 (samplingRate != inputDesc->mSamplingRate) ||
976 (format != inputDesc->mFormat) ||
Eric Laurent70c236c2012-03-28 11:27:13 -0700977 (channelMask != inputDesc->mChannelMask)) {
978 ALOGV("getInput() failed opening input: samplingRate %d, format %d, channelMask %d",
979 samplingRate, format, channelMask);
Dima Zavinf0121592011-04-19 16:33:12 -0700980 if (input != 0) {
981 mpClientInterface->closeInput(input);
982 }
983 delete inputDesc;
984 return 0;
985 }
986 mInputs.add(input, inputDesc);
987 return input;
988}
989
990status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input)
991{
Steve Block6a705182011-10-20 11:56:19 +0100992 ALOGV("startInput() input %d", input);
Dima Zavinf0121592011-04-19 16:33:12 -0700993 ssize_t index = mInputs.indexOfKey(input);
994 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +0000995 ALOGW("startInput() unknow input %d", input);
Dima Zavinf0121592011-04-19 16:33:12 -0700996 return BAD_VALUE;
997 }
998 AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
999
1000#ifdef AUDIO_POLICY_TEST
1001 if (mTestInput == 0)
1002#endif //AUDIO_POLICY_TEST
1003 {
Eric Laurentfc9b2452013-09-09 10:42:47 -07001004 // refuse 2 active AudioRecord clients at the same time except if the active input
1005 // uses AUDIO_SOURCE_HOTWORD in which case it is closed.
1006 audio_io_handle_t activeInput = getActiveInput();
1007 if (!isVirtualInputDevice(inputDesc->mDevice) && activeInput != 0) {
1008 AudioInputDescriptor *activeDesc = mInputs.valueFor(activeInput);
1009 if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) {
1010 ALOGW("startInput() preempting already started low-priority input %d", activeInput);
1011 stopInput(activeInput);
1012 releaseInput(activeInput);
1013 } else {
1014 ALOGW("startInput() input %d failed: other input already started..", input);
1015 return INVALID_OPERATION;
1016 }
Dima Zavinf0121592011-04-19 16:33:12 -07001017 }
1018 }
1019
Eric Laurent66707432013-05-17 14:11:27 -07001020 audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
1021 if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
1022 inputDesc->mDevice = newDevice;
1023 }
Jeff Brownb96b2832013-08-16 20:10:48 -07001024
1025 // automatically enable the remote submix output when input is started
1026 if (audio_is_remote_submix_device(inputDesc->mDevice)) {
1027 setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
1028 AudioSystem::DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
1029 }
1030
Dima Zavinf0121592011-04-19 16:33:12 -07001031 AudioParameter param = AudioParameter();
1032 param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
1033
Eric Laurentfc9b2452013-09-09 10:42:47 -07001034 int aliasSource = (inputDesc->mInputSource == AUDIO_SOURCE_HOTWORD) ?
1035 AUDIO_SOURCE_VOICE_RECOGNITION : inputDesc->mInputSource;
1036
1037 param.addInt(String8(AudioParameter::keyInputSource), aliasSource);
Steve Block6a705182011-10-20 11:56:19 +01001038 ALOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
Dima Zavinf0121592011-04-19 16:33:12 -07001039
1040 mpClientInterface->setParameters(input, param.toString());
1041
1042 inputDesc->mRefCount = 1;
1043 return NO_ERROR;
1044}
1045
1046status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input)
1047{
Steve Block6a705182011-10-20 11:56:19 +01001048 ALOGV("stopInput() input %d", input);
Dima Zavinf0121592011-04-19 16:33:12 -07001049 ssize_t index = mInputs.indexOfKey(input);
1050 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +00001051 ALOGW("stopInput() unknow input %d", input);
Dima Zavinf0121592011-04-19 16:33:12 -07001052 return BAD_VALUE;
1053 }
1054 AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
1055
1056 if (inputDesc->mRefCount == 0) {
Steve Block64cca042012-01-05 23:27:53 +00001057 ALOGW("stopInput() input %d already stopped", input);
Dima Zavinf0121592011-04-19 16:33:12 -07001058 return INVALID_OPERATION;
1059 } else {
Jeff Brownb96b2832013-08-16 20:10:48 -07001060 // automatically disable the remote submix output when input is stopped
1061 if (audio_is_remote_submix_device(inputDesc->mDevice)) {
1062 setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
1063 AudioSystem::DEVICE_STATE_UNAVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
1064 }
1065
Dima Zavinf0121592011-04-19 16:33:12 -07001066 AudioParameter param = AudioParameter();
1067 param.addInt(String8(AudioParameter::keyRouting), 0);
1068 mpClientInterface->setParameters(input, param.toString());
1069 inputDesc->mRefCount = 0;
1070 return NO_ERROR;
1071 }
1072}
1073
1074void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input)
1075{
Steve Block6a705182011-10-20 11:56:19 +01001076 ALOGV("releaseInput() %d", input);
Dima Zavinf0121592011-04-19 16:33:12 -07001077 ssize_t index = mInputs.indexOfKey(input);
1078 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +00001079 ALOGW("releaseInput() releasing unknown input %d", input);
Dima Zavinf0121592011-04-19 16:33:12 -07001080 return;
1081 }
1082 mpClientInterface->closeInput(input);
1083 delete mInputs.valueAt(index);
1084 mInputs.removeItem(input);
Steve Block6a705182011-10-20 11:56:19 +01001085 ALOGV("releaseInput() exit");
Dima Zavinf0121592011-04-19 16:33:12 -07001086}
1087
1088void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
1089 int indexMin,
1090 int indexMax)
1091{
Steve Block6a705182011-10-20 11:56:19 +01001092 ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
Dima Zavinf0121592011-04-19 16:33:12 -07001093 if (indexMin < 0 || indexMin >= indexMax) {
Steve Block64cca042012-01-05 23:27:53 +00001094 ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
Dima Zavinf0121592011-04-19 16:33:12 -07001095 return;
1096 }
1097 mStreams[stream].mIndexMin = indexMin;
1098 mStreams[stream].mIndexMax = indexMax;
1099}
1100
Eric Laurentc6f331b2011-12-14 18:18:36 -08001101status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream,
1102 int index,
1103 audio_devices_t device)
Dima Zavinf0121592011-04-19 16:33:12 -07001104{
1105
1106 if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
1107 return BAD_VALUE;
1108 }
Eric Laurentc6f331b2011-12-14 18:18:36 -08001109 if (!audio_is_output_device(device)) {
1110 return BAD_VALUE;
1111 }
Dima Zavinf0121592011-04-19 16:33:12 -07001112
1113 // Force max volume if stream cannot be muted
1114 if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
1115
Eric Laurentb4696fc2012-02-17 10:55:44 -08001116 ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
Eric Laurentc6f331b2011-12-14 18:18:36 -08001117 stream, device, index);
1118
1119 // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
1120 // clear all device specific values
1121 if (device == AUDIO_DEVICE_OUT_DEFAULT) {
1122 mStreams[stream].mIndexCur.clear();
1123 }
1124 mStreams[stream].mIndexCur.add(device, index);
Dima Zavinf0121592011-04-19 16:33:12 -07001125
1126 // compute and apply stream volume on all outputs according to connected device
1127 status_t status = NO_ERROR;
1128 for (size_t i = 0; i < mOutputs.size(); i++) {
Eric Laurentc5eb8b42012-02-15 18:40:31 -08001129 audio_devices_t curDevice =
Jean-Michel Trivic8101f52012-08-24 11:45:04 -07001130 getDeviceForVolume(mOutputs.valueAt(i)->device());
Ricardo Cerqueira3bd74772013-11-01 20:38:49 +00001131#ifndef ICS_AUDIO_BLOB
1132 if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice))
1133#endif
1134 {
Eric Laurentc5eb8b42012-02-15 18:40:31 -08001135 status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
1136 if (volStatus != NO_ERROR) {
1137 status = volStatus;
1138 }
Dima Zavinf0121592011-04-19 16:33:12 -07001139 }
1140 }
1141 return status;
1142}
1143
Eric Laurentc6f331b2011-12-14 18:18:36 -08001144status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream,
1145 int *index,
1146 audio_devices_t device)
Dima Zavinf0121592011-04-19 16:33:12 -07001147{
Eric Laurentc6f331b2011-12-14 18:18:36 -08001148 if (index == NULL) {
Dima Zavinf0121592011-04-19 16:33:12 -07001149 return BAD_VALUE;
1150 }
Ricardo Cerqueira3bd74772013-11-01 20:38:49 +00001151#ifndef ICS_AUDIO_BLOB
Eric Laurentc6f331b2011-12-14 18:18:36 -08001152 if (!audio_is_output_device(device)) {
1153 return BAD_VALUE;
1154 }
1155 // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to
1156 // the strategy the stream belongs to.
1157 if (device == AUDIO_DEVICE_OUT_DEFAULT) {
Jean-Michel Trivic8101f52012-08-24 11:45:04 -07001158 device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
Eric Laurentc6f331b2011-12-14 18:18:36 -08001159 }
1160 device = getDeviceForVolume(device);
1161
1162 *index = mStreams[stream].getVolumeIndex(device);
Ricardo Cerqueira3bd74772013-11-01 20:38:49 +00001163#else
1164 *index = mStreams[stream].mIndexCur.valueAt(0);
1165#endif
Eric Laurentc6f331b2011-12-14 18:18:36 -08001166 ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
Dima Zavinf0121592011-04-19 16:33:12 -07001167 return NO_ERROR;
1168}
1169
Eric Laurent45c76392013-09-12 17:39:21 -07001170audio_io_handle_t AudioPolicyManagerBase::selectOutputForEffects(
1171 const SortedVector<audio_io_handle_t>& outputs)
1172{
1173 // select one output among several suitable for global effects.
1174 // The priority is as follows:
1175 // 1: An offloaded output. If the effect ends up not being offloadable,
1176 // AudioFlinger will invalidate the track and the offloaded output
1177 // will be closed causing the effect to be moved to a PCM output.
1178 // 2: A deep buffer output
1179 // 3: the first output in the list
1180
1181 if (outputs.size() == 0) {
1182 return 0;
1183 }
1184
1185 audio_io_handle_t outputOffloaded = 0;
1186 audio_io_handle_t outputDeepBuffer = 0;
1187
1188 for (size_t i = 0; i < outputs.size(); i++) {
1189 AudioOutputDescriptor *desc = mOutputs.valueFor(outputs[i]);
1190 ALOGV("selectOutputForEffects outputs[%d] flags %x", i, desc->mFlags);
1191 if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
1192 outputOffloaded = outputs[i];
1193 }
1194 if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
1195 outputDeepBuffer = outputs[i];
1196 }
1197 }
1198
1199 ALOGV("selectOutputForEffects outputOffloaded %d outputDeepBuffer %d",
1200 outputOffloaded, outputDeepBuffer);
1201 if (outputOffloaded != 0) {
1202 return outputOffloaded;
1203 }
1204 if (outputDeepBuffer != 0) {
1205 return outputDeepBuffer;
1206 }
1207
1208 return outputs[0];
1209}
1210
Glenn Kastenc94dccc2012-07-24 07:51:26 -07001211audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(const effect_descriptor_t *desc)
Dima Zavinf0121592011-04-19 16:33:12 -07001212{
Dima Zavinf0121592011-04-19 16:33:12 -07001213 // apply simple rule where global effects are attached to the same output as MUSIC streams
Marco Nelissen46604552012-05-31 10:50:29 -07001214
1215 routing_strategy strategy = getStrategy(AudioSystem::MUSIC);
1216 audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
Eric Laurentc9525272012-06-21 09:55:49 -07001217 SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(device, mOutputs);
Eric Laurent45c76392013-09-12 17:39:21 -07001218
1219 audio_io_handle_t output = selectOutputForEffects(dstOutputs);
1220 ALOGV("getOutputForEffect() got output %d for fx %s flags %x",
1221 output, (desc == NULL) ? "unspecified" : desc->name, (desc == NULL) ? 0 : desc->flags);
1222
1223 return output;
Dima Zavinf0121592011-04-19 16:33:12 -07001224}
1225
Glenn Kastenc94dccc2012-07-24 07:51:26 -07001226status_t AudioPolicyManagerBase::registerEffect(const effect_descriptor_t *desc,
Eric Laurent1c65a492011-06-17 21:51:11 -07001227 audio_io_handle_t io,
Dima Zavinf0121592011-04-19 16:33:12 -07001228 uint32_t strategy,
1229 int session,
1230 int id)
1231{
Eric Laurent1c65a492011-06-17 21:51:11 -07001232 ssize_t index = mOutputs.indexOfKey(io);
Dima Zavinf0121592011-04-19 16:33:12 -07001233 if (index < 0) {
Eric Laurent1c65a492011-06-17 21:51:11 -07001234 index = mInputs.indexOfKey(io);
1235 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +00001236 ALOGW("registerEffect() unknown io %d", io);
Eric Laurent1c65a492011-06-17 21:51:11 -07001237 return INVALID_OPERATION;
1238 }
Dima Zavinf0121592011-04-19 16:33:12 -07001239 }
1240
Dima Zavinf0121592011-04-19 16:33:12 -07001241 if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
Steve Block64cca042012-01-05 23:27:53 +00001242 ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
Dima Zavinf0121592011-04-19 16:33:12 -07001243 desc->name, desc->memoryUsage);
1244 return INVALID_OPERATION;
1245 }
Dima Zavinf0121592011-04-19 16:33:12 -07001246 mTotalEffectsMemory += desc->memoryUsage;
Steve Block6a705182011-10-20 11:56:19 +01001247 ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
Eric Laurent1c65a492011-06-17 21:51:11 -07001248 desc->name, io, strategy, session, id);
Steve Block6a705182011-10-20 11:56:19 +01001249 ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
Dima Zavinf0121592011-04-19 16:33:12 -07001250
1251 EffectDescriptor *pDesc = new EffectDescriptor();
1252 memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));
Eric Laurent1c65a492011-06-17 21:51:11 -07001253 pDesc->mIo = io;
Dima Zavinf0121592011-04-19 16:33:12 -07001254 pDesc->mStrategy = (routing_strategy)strategy;
1255 pDesc->mSession = session;
Eric Laurent582a1572011-08-10 20:16:23 -07001256 pDesc->mEnabled = false;
1257
Dima Zavinf0121592011-04-19 16:33:12 -07001258 mEffects.add(id, pDesc);
1259
1260 return NO_ERROR;
1261}
1262
1263status_t AudioPolicyManagerBase::unregisterEffect(int id)
1264{
1265 ssize_t index = mEffects.indexOfKey(id);
1266 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +00001267 ALOGW("unregisterEffect() unknown effect ID %d", id);
Dima Zavinf0121592011-04-19 16:33:12 -07001268 return INVALID_OPERATION;
1269 }
1270
1271 EffectDescriptor *pDesc = mEffects.valueAt(index);
1272
Eric Laurent582a1572011-08-10 20:16:23 -07001273 setEffectEnabled(pDesc, false);
1274
Dima Zavinf0121592011-04-19 16:33:12 -07001275 if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) {
Steve Block64cca042012-01-05 23:27:53 +00001276 ALOGW("unregisterEffect() memory %d too big for total %d",
Dima Zavinf0121592011-04-19 16:33:12 -07001277 pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
1278 pDesc->mDesc.memoryUsage = mTotalEffectsMemory;
1279 }
1280 mTotalEffectsMemory -= pDesc->mDesc.memoryUsage;
Steve Block6a705182011-10-20 11:56:19 +01001281 ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
Eric Laurent582a1572011-08-10 20:16:23 -07001282 pDesc->mDesc.name, id, pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
Dima Zavinf0121592011-04-19 16:33:12 -07001283
1284 mEffects.removeItem(id);
1285 delete pDesc;
1286
1287 return NO_ERROR;
1288}
1289
Eric Laurent582a1572011-08-10 20:16:23 -07001290status_t AudioPolicyManagerBase::setEffectEnabled(int id, bool enabled)
1291{
1292 ssize_t index = mEffects.indexOfKey(id);
1293 if (index < 0) {
Steve Block64cca042012-01-05 23:27:53 +00001294 ALOGW("unregisterEffect() unknown effect ID %d", id);
Eric Laurent582a1572011-08-10 20:16:23 -07001295 return INVALID_OPERATION;
1296 }
1297
1298 return setEffectEnabled(mEffects.valueAt(index), enabled);
1299}
1300
1301status_t AudioPolicyManagerBase::setEffectEnabled(EffectDescriptor *pDesc, bool enabled)
1302{
1303 if (enabled == pDesc->mEnabled) {
Steve Block6a705182011-10-20 11:56:19 +01001304 ALOGV("setEffectEnabled(%s) effect already %s",
Eric Laurent582a1572011-08-10 20:16:23 -07001305 enabled?"true":"false", enabled?"enabled":"disabled");
1306 return INVALID_OPERATION;
1307 }
1308
1309 if (enabled) {
1310 if (mTotalEffectsCpuLoad + pDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
Steve Block64cca042012-01-05 23:27:53 +00001311 ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
Eric Laurent582a1572011-08-10 20:16:23 -07001312 pDesc->mDesc.name, (float)pDesc->mDesc.cpuLoad/10);
1313 return INVALID_OPERATION;
1314 }
1315 mTotalEffectsCpuLoad += pDesc->mDesc.cpuLoad;
Steve Block6a705182011-10-20 11:56:19 +01001316 ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
Eric Laurent582a1572011-08-10 20:16:23 -07001317 } else {
1318 if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
Steve Block64cca042012-01-05 23:27:53 +00001319 ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
Eric Laurent582a1572011-08-10 20:16:23 -07001320 pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
1321 pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
1322 }
1323 mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
Steve Block6a705182011-10-20 11:56:19 +01001324 ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
Eric Laurent582a1572011-08-10 20:16:23 -07001325 }
1326 pDesc->mEnabled = enabled;
1327 return NO_ERROR;
1328}
1329
Eric Laurent000bb512013-10-12 16:29:39 -07001330bool AudioPolicyManagerBase::isNonOffloadableEffectEnabled()
1331{
1332 for (size_t i = 0; i < mEffects.size(); i++) {
1333 const EffectDescriptor * const pDesc = mEffects.valueAt(i);
1334 if (pDesc->mEnabled && (pDesc->mStrategy == STRATEGY_MEDIA) &&
1335 ((pDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
1336 ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
1337 pDesc->mDesc.name, pDesc->mSession);
1338 return true;
1339 }
1340 }
1341 return false;
1342}
1343
Dima Zavinf0121592011-04-19 16:33:12 -07001344bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const
1345{
1346 nsecs_t sysTime = systemTime();
1347 for (size_t i = 0; i < mOutputs.size(); i++) {
Eric Laurent80f5b042013-03-25 09:58:09 -07001348 const AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
1349 if (outputDesc->isStreamActive((AudioSystem::stream_type)stream, inPastMs, sysTime)) {
Dima Zavinf0121592011-04-19 16:33:12 -07001350 return true;
1351 }
1352 }
1353 return false;
1354}
1355
Jean-Michel Trividc3bf1a2013-02-04 16:28:31 -08001356bool AudioPolicyManagerBase::isStreamActiveRemotely(int stream, uint32_t inPastMs) const
1357{
1358 nsecs_t sysTime = systemTime();
1359 for (size_t i = 0; i < mOutputs.size(); i++) {
1360 const AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);
Eric Laurent80f5b042013-03-25 09:58:09 -07001361 if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
1362 outputDesc->isStreamActive((AudioSystem::stream_type)stream, inPastMs, sysTime)) {
Jean-Michel Trividc3bf1a2013-02-04 16:28:31 -08001363 return true;
1364 }
1365 }
1366 return false;
1367}
1368
Jean-Michel Triviabc55c62012-10-10 12:39:04 -07001369bool AudioPolicyManagerBase::isSourceActive(audio_source_t source) const
1370{
1371 for (size_t i = 0; i < mInputs.size(); i++) {
1372 const AudioInputDescriptor * inputDescriptor = mInputs.valueAt(i);
Eric Laurentfc9b2452013-09-09 10:42:47 -07001373 if ((inputDescriptor->mInputSource == (int)source ||
1374 (source == (audio_source_t)AUDIO_SOURCE_VOICE_RECOGNITION &&
1375 inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD))
1376 && (inputDescriptor->mRefCount > 0)) {
Jean-Michel Triviabc55c62012-10-10 12:39:04 -07001377 return true;
1378 }
1379 }
1380 return false;
1381}
1382
1383
Dima Zavinf0121592011-04-19 16:33:12 -07001384status_t AudioPolicyManagerBase::dump(int fd)
1385{
1386 const size_t SIZE = 256;
1387 char buffer[SIZE];
1388 String8 result;
1389
1390 snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
1391 result.append(buffer);
Eric Laurentb4696fc2012-02-17 10:55:44 -08001392
Eric Laurent70c236c2012-03-28 11:27:13 -07001393 snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput);
Dima Zavinf0121592011-04-19 16:33:12 -07001394 result.append(buffer);
1395 snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
1396 result.append(buffer);
Dima Zavinf0121592011-04-19 16:33:12 -07001397 snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
1398 result.append(buffer);
Eric Laurent599a1fc2012-04-06 09:07:07 -07001399 snprintf(buffer, SIZE, " USB audio ALSA %s\n", mUsbCardAndDevice.string());
1400 result.append(buffer);
Dima Zavinf0121592011-04-19 16:33:12 -07001401 snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
1402 result.append(buffer);
1403 snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
1404 result.append(buffer);
1405 snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
1406 result.append(buffer);
Dima Zavinf0121592011-04-19 16:33:12 -07001407 snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
1408 result.append(buffer);
1409 snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
1410 result.append(buffer);
1411 snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
1412 result.append(buffer);
1413 snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]);
1414 result.append(buffer);
Eric Laurent738207d2012-10-08 15:53:09 -07001415 snprintf(buffer, SIZE, " Force use for system %d\n", mForceUse[AudioSystem::FOR_SYSTEM]);
1416 result.append(buffer);
Dima Zavinf0121592011-04-19 16:33:12 -07001417 write(fd, result.string(), result.size());
1418
Eric Laurent5ccdf142012-03-20 13:44:51 -07001419
Eric Laurent70c236c2012-03-28 11:27:13 -07001420 snprintf(buffer, SIZE, "\nHW Modules dump:\n");
Eric Laurent5ccdf142012-03-20 13:44:51 -07001421 write(fd, buffer, strlen(buffer));
Eric Laurent70c236c2012-03-28 11:27:13 -07001422 for (size_t i = 0; i < mHwModules.size(); i++) {
1423 snprintf(buffer, SIZE, "- HW Module %d:\n", i + 1);
Eric Laurent5ccdf142012-03-20 13:44:51 -07001424 write(fd, buffer, strlen(buffer));
Eric Laurent70c236c2012-03-28 11:27:13 -07001425 mHwModules[i]->dump(fd);
Eric Laurent5ccdf142012-03-20 13:44:51 -07001426 }
1427
Dima Zavinf0121592011-04-19 16:33:12 -07001428 snprintf(buffer, SIZE, "\nOutputs dump:\n");
1429 write(fd, buffer, strlen(buffer));
1430 for (size_t i = 0; i < mOutputs.size(); i++) {
1431 snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
1432 write(fd, buffer, strlen(buffer));
1433 mOutputs.valueAt(i)->dump(fd);
1434 }
1435
1436 snprintf(buffer, SIZE, "\nInputs dump:\n");
1437 write(fd, buffer, strlen(buffer));
1438 for (size_t i = 0; i < mInputs.size(); i++) {
1439 snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
1440 write(fd, buffer, strlen(buffer));
1441 mInputs.valueAt(i)->dump(fd);
1442 }
1443
1444 snprintf(buffer, SIZE, "\nStreams dump:\n");
1445 write(fd, buffer, strlen(buffer));
Eric Laurentc6f331b2011-12-14 18:18:36 -08001446 snprintf(buffer, SIZE,
1447 " Stream Can be muted Index Min Index Max Index Cur [device : index]...\n");
Dima Zavinf0121592011-04-19 16:33:12 -07001448 write(fd, buffer, strlen(buffer));
1449 for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
Eric Laurentc6f331b2011-12-14 18:18:36 -08001450 snprintf(buffer, SIZE, " %02d ", i);
Dima Zavinf0121592011-04-19 16:33:12 -07001451 write(fd, buffer, strlen(buffer));
Eric Laurentc6f331b2011-12-14 18:18:36 -08001452 mStreams[i].dump(fd);
Dima Zavinf0121592011-04-19 16:33:12 -07001453 }
1454
1455 snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
1456 (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
1457 write(fd, buffer, strlen(buffer));
1458
1459 snprintf(buffer, SIZE, "Registered effects:\n");
1460 write(fd, buffer, strlen(buffer));
1461 for (size_t i = 0; i < mEffects.size(); i++) {
1462 snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
1463 write(fd, buffer, strlen(buffer));
1464 mEffects.valueAt(i)->dump(fd);
1465 }
1466
1467
1468 return NO_ERROR;
1469}
1470
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001471// This function checks for the parameters which can be offloaded.
1472// This can be enhanced depending on the capability of the DSP and policy
1473// of the system.
Richard Fitzgeraldb4d07b92013-03-25 16:18:26 +00001474bool AudioPolicyManagerBase::isOffloadSupported(const audio_offload_info_t& offloadInfo)
1475{
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001476 ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d,"
1477 " BitRate=%u, duration=%lld us, has_video=%d",
1478 offloadInfo.sample_rate, offloadInfo.channel_mask,
1479 offloadInfo.format,
1480 offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us,
1481 offloadInfo.has_video);
1482
1483 // Check if offload has been disabled
1484 char propValue[PROPERTY_VALUE_MAX];
1485 if (property_get("audio.offload.disable", propValue, "0")) {
1486 if (atoi(propValue) != 0) {
1487 ALOGV("offload disabled by audio.offload.disable=%s", propValue );
1488 return false;
1489 }
1490 }
1491
1492 // Check if stream type is music, then only allow offload as of now.
1493 if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
1494 {
Eric Laurent41b150b2013-08-29 17:29:19 -07001495 ALOGV("isOffloadSupported: stream_type != MUSIC, returning false");
1496 return false;
1497 }
1498
1499 //TODO: enable audio offloading with video when ready
1500 if (offloadInfo.has_video)
1501 {
Ricardo Cerqueiracac7ba42013-12-14 00:16:39 +00001502 if(property_get("av.offload.enable", propValue, "false")) {
Krishnankutty Kolathappillyc9c7bd62013-10-29 00:20:45 -07001503 bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
1504 if (!prop_enabled) {
1505 ALOGW("offload disabled by av.offload.enable = %s ", propValue );
1506 return false;
1507 }
1508 }
Ravi Kumar Alamanda0d27bcb2013-12-11 00:29:11 -08001509 if(offloadInfo.is_streaming &&
1510 property_get("av.streaming.offload.enable", propValue, "false")) {
1511 bool prop_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
1512 if (!prop_enabled) {
1513 ALOGW("offload disabled by av.streaming.offload.enable = %s ", propValue );
1514 return false;
1515 }
1516 }
Krishnankutty Kolathappillyc9c7bd62013-10-29 00:20:45 -07001517 ALOGV("isOffloadSupported: has_video == true, property\
1518 set to enable offload");
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001519 }
1520
1521 //If duration is less than minimum value defined in property, return false
1522 if (property_get("audio.offload.min.duration.secs", propValue, NULL)) {
1523 if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) {
1524 ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue);
1525 return false;
1526 }
1527 } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) {
1528 ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
Mingming Yin55a3ee82013-11-13 15:27:44 -08001529 //duration checks only valid for MP3/AAC formats,
1530 //do not check duration for other audio formats, e.g. dolby AAC/AC3 and amrwb+ formats
1531 if (offloadInfo.format == AUDIO_FORMAT_MP3 || offloadInfo.format == AUDIO_FORMAT_AAC)
1532 return false;
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001533 }
1534
Eric Laurent000bb512013-10-12 16:29:39 -07001535 // Do not allow offloading if one non offloadable effect is enabled. This prevents from
1536 // creating an offloaded track and tearing it down immediately after start when audioflinger
1537 // detects there is an active non offloadable effect.
1538 // FIXME: We should check the audio session here but we do not have it in this context.
1539 // This may prevent offloading in rare situations where effects are left active by apps
1540 // in the background.
1541 if (isNonOffloadableEffectEnabled()) {
1542 return false;
1543 }
1544
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001545 // See if there is a profile to support this.
1546 // AUDIO_DEVICE_NONE
1547 IOProfile *profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */,
1548 offloadInfo.sample_rate,
1549 offloadInfo.format,
1550 offloadInfo.channel_mask,
1551 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
1552 ALOGV("isOffloadSupported() profile %sfound", profile != NULL ? "" : "NOT ");
1553 return (profile != NULL);
Richard Fitzgeraldb4d07b92013-03-25 16:18:26 +00001554}
1555
Dima Zavinf0121592011-04-19 16:33:12 -07001556// ----------------------------------------------------------------------------
1557// AudioPolicyManagerBase
1558// ----------------------------------------------------------------------------
1559
1560AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
1561 :
1562#ifdef AUDIO_POLICY_TEST
1563 Thread(false),
1564#endif //AUDIO_POLICY_TEST
Eric Laurent70c236c2012-03-28 11:27:13 -07001565 mPrimaryOutput((audio_io_handle_t)0),
Eric Laurented8f62d2012-08-28 14:32:21 -07001566 mAvailableOutputDevices(AUDIO_DEVICE_NONE),
Glenn Kastenca0657a2012-01-18 15:24:50 -08001567 mPhoneState(AudioSystem::MODE_NORMAL),
Dima Zavinf0121592011-04-19 16:33:12 -07001568 mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
1569 mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
Jean-Michel Trivi18fc0942013-11-14 16:30:20 -08001570 mA2dpSuspended(false), mHasA2dp(false), mHasUsb(false), mHasRemoteSubmix(false),
1571 mSpeakerDrcEnabled(false)
Dima Zavinf0121592011-04-19 16:33:12 -07001572{
1573 mpClientInterface = clientInterface;
1574
1575 for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
1576 mForceUse[i] = AudioSystem::FORCE_NONE;
1577 }
1578
Dima Zavinf0121592011-04-19 16:33:12 -07001579 mA2dpDeviceAddress = String8("");
Dima Zavinf0121592011-04-19 16:33:12 -07001580 mScoDeviceAddress = String8("");
Eric Laurent599a1fc2012-04-06 09:07:07 -07001581 mUsbCardAndDevice = String8("");
Dima Zavinf0121592011-04-19 16:33:12 -07001582
Dima Zavin5ec145d2012-04-23 16:51:00 -07001583 if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
1584 if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
Dima Zavin739022f2012-04-24 00:21:59 -07001585 ALOGE("could not load audio policy configuration file, setting defaults");
1586 defaultAudioPolicyConfig();
Dima Zavin5ec145d2012-04-23 16:51:00 -07001587 }
Eric Laurent5ccdf142012-03-20 13:44:51 -07001588 }
Dima Zavinf0121592011-04-19 16:33:12 -07001589
Jean-Michel Trivi18fc0942013-11-14 16:30:20 -08001590 // must be done after reading the policy
1591 initializeVolumeCurves();
1592
Eric Laurent5ccdf142012-03-20 13:44:51 -07001593 // open all output streams needed to access attached devices
Eric Laurent70c236c2012-03-28 11:27:13 -07001594 for (size_t i = 0; i < mHwModules.size(); i++) {
1595 mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
1596 if (mHwModules[i]->mHandle == 0) {
1597 ALOGW("could not open HW module %s", mHwModules[i]->mName);
1598 continue;
1599 }
1600 // open all output streams needed to access attached devices
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001601 // except for direct output streams that are only opened when they are actually
1602 // required by an app.
Eric Laurent70c236c2012-03-28 11:27:13 -07001603 for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
1604 {
1605 const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];
Eric Laurent5ccdf142012-03-20 13:44:51 -07001606
Richard Fitzgeralda527ffd2013-05-13 11:52:24 +01001607 if ((outProfile->mSupportedDevices & mAttachedOutputDevices) &&
1608 ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
Eric Laurent70c236c2012-03-28 11:27:13 -07001609 AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
Eric Laurent70c236c2012-03-28 11:27:13 -07001610 outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice &
1611 outProfile->mSupportedDevices);
Eric Laurent70c236c2012-03-28 11:27:13 -07001612 audio_io_handle_t output = mpClientInterface->openOutput(
1613 outProfile->mModule->mHandle,
1614 &outputDesc->mDevice,
1615 &outputDesc->mSamplingRate,
1616 &outputDesc->mFormat,
1617 &outputDesc->mChannelMask,
1618 &outputDesc->mLatency,
1619 outputDesc->mFlags);
1620 if (output == 0) {
1621 delete outputDesc;
1622 } else {
1623 mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices |
1624 (outProfile->mSupportedDevices & mAttachedOutputDevices));
1625 if (mPrimaryOutput == 0 &&
Eric Laurent0977cf52012-04-18 09:28:52 -07001626 outProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Eric Laurent70c236c2012-03-28 11:27:13 -07001627 mPrimaryOutput = output;
1628 }
1629 addOutput(output, outputDesc);
1630 setOutputDevice(output,
1631 (audio_devices_t)(mDefaultOutputDevice &
1632 outProfile->mSupportedDevices),
1633 true);
Eric Laurentb4696fc2012-02-17 10:55:44 -08001634 }
Eric Laurentb4696fc2012-02-17 10:55:44 -08001635 }
1636 }
Dima Zavinf0121592011-04-19 16:33:12 -07001637 }
1638
Eric Laurent5ccdf142012-03-20 13:44:51 -07001639 ALOGE_IF((mAttachedOutputDevices & ~mAvailableOutputDevices),
Eric Laurentb4696fc2012-02-17 10:55:44 -08001640 "Not output found for attached devices %08x",
Eric Laurent5ccdf142012-03-20 13:44:51 -07001641 (mAttachedOutputDevices & ~mAvailableOutputDevices));
Eric Laurentb4696fc2012-02-17 10:55:44 -08001642
1643 ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
1644
Eric Laurentc9525272012-06-21 09:55:49 -07001645 updateDevicesAndOutputs();
Eric Laurent3cdfddf2012-04-30 18:28:24 -07001646
Dima Zavinf0121592011-04-19 16:33:12 -07001647#ifdef AUDIO_POLICY_TEST
Eric Laurentb4696fc2012-02-17 10:55:44 -08001648 if (mPrimaryOutput != 0) {
Dima Zavinf0121592011-04-19 16:33:12 -07001649 AudioParameter outputCmd = AudioParameter();
1650 outputCmd.addInt(String8("set_id"), 0);
Eric Laurentb4696fc2012-02-17 10:55:44 -08001651 mpClientInterface->setParameters(mPrimaryOutput, outputCmd.toString());
Dima Zavinf0121592011-04-19 16:33:12 -07001652
Jean-Michel Trivic8101f52012-08-24 11:45:04 -07001653 mTestDevice = AUDIO_DEVICE_OUT_SPEAKER;
Dima Zavinf0121592011-04-19 16:33:12 -07001654 mTestSamplingRate = 44100;
1655 mTestFormat = AudioSystem::PCM_16_BIT;
1656 mTestChannels = AudioSystem::CHANNEL_OUT_STEREO;
1657 mTestLatencyMs = 0;
1658 mCurOutput = 0;
1659 mDirectOutput = false;
1660 for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
1661 mTestOutputs[i] = 0;
1662 }
1663
1664 const size_t SIZE = 256;
1665 char buffer[SIZE];
1666 snprintf(buffer, SIZE, "AudioPolicyManagerTest");
1667 run(buffer, ANDROID_PRIORITY_AUDIO);
1668 }
1669#endif //AUDIO_POLICY_TEST
1670}
1671
1672AudioPolicyManagerBase::~AudioPolicyManagerBase()
1673{
1674#ifdef AUDIO_POLICY_TEST
1675 exit();
1676#endif //AUDIO_POLICY_TEST
1677 for (size_t i = 0; i < mOutputs.size(); i++) {
1678 mpClientInterface->closeOutput(mOutputs.keyAt(i));
1679 delete mOutputs.valueAt(i);
1680 }
Dima Zavinf0121592011-04-19 16:33:12 -0700