Loading media/java/android/media/AudioManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -4053,6 +4053,36 @@ public class AudioManager { } } /** * Indicate A2DP source or sink active device change and eventually suppress * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent. * @param device Bluetooth device connected/disconnected * @param state new connection state (BluetoothProfile.STATE_xxx) * @param profile profile for the A2DP device * (either {@link android.bluetooth.BluetoothProfile.A2DP} or * {@link android.bluetooth.BluetoothProfile.A2DP_SINK}) * @param a2dpVolume New volume for the connecting device. Does nothing if * disconnecting. Pass value -1 in case you want this field to be ignored * @param suppressNoisyIntent if true the * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent. * @return a delay in ms that the caller should wait before broadcasting * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. * {@hide} */ public int handleBluetoothA2dpActiveDeviceChange( BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { final IAudioService service = getService(); int delay = 0; try { delay = service.handleBluetoothA2dpActiveDeviceChange(device, state, profile, suppressNoisyIntent, a2dpVolume); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } return delay; } /** {@hide} */ public IRingtonePlayer getRingtonePlayer() { try { Loading media/java/android/media/IAudioService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,9 @@ interface IAudioService { void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device); int handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume); AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer); boolean isCameraSoundForced(); Loading services/core/java/com/android/server/audio/AudioService.java +122 −3 Original line number Diff line number Diff line Loading @@ -270,6 +270,7 @@ public class AudioService extends IAudioService.Stub private static final int MSG_DISABLE_AUDIO_FOR_UID = 104; private static final int MSG_SET_HEARING_AID_CONNECTION_STATE = 105; private static final int MSG_BTA2DP_DOCK_TIMEOUT = 106; private static final int MSG_A2DP_ACTIVE_DEVICE_CHANGE = 107; // end of messages handled under wakelock private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; Loading Loading @@ -4673,6 +4674,7 @@ public class AudioService extends IAudioService.Stub msg == MSG_SET_HEARING_AID_CONNECTION_STATE || msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE || msg == MSG_A2DP_DEVICE_CONFIG_CHANGE || msg == MSG_A2DP_ACTIVE_DEVICE_CHANGE || msg == MSG_BTA2DP_DOCK_TIMEOUT) { if (mLastDeviceConnectMsgTime >= time) { // add a little delay to make sure messages are ordered as expected Loading Loading @@ -4892,6 +4894,61 @@ public class AudioService extends IAudioService.Stub } } /** * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int, * boolean, int) */ public int handleBluetoothA2dpActiveDeviceChange( BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { throw new IllegalArgumentException("invalid profile " + profile); } synchronized (mConnectedDevices) { if (state == BluetoothA2dp.STATE_CONNECTED) { for (int i = 0; i < mConnectedDevices.size(); i++) { DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i); if (deviceSpec.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) { continue; } // If A2DP device exists, this is either an active device change or // device config change String existingDevicekey = mConnectedDevices.keyAt(i); String deviceName = device.getName(); String address = device.getAddress(); String newDeviceKey = makeDeviceListKey( AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address); int a2dpCodec = getA2dpCodec(device); // Device not equal to existing device, active device change if (!TextUtils.equals(existingDevicekey, newDeviceKey)) { mConnectedDevices.remove(existingDevicekey); mConnectedDevices.put(newDeviceKey, new DeviceListSpec( AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName, address, a2dpCodec)); queueMsgUnderWakeLock(mAudioHandler, MSG_A2DP_ACTIVE_DEVICE_CHANGE, 0, 0, new BluetoothA2dpDeviceInfo( device, a2dpVolume, a2dpCodec), 0 /* delay */); return 0; } else { // Device config change for existing device handleBluetoothA2dpDeviceConfigChange(device); return 0; } } } } // New device connection or a device disconnect return setBluetoothA2dpDeviceConnectionStateInt( device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume); } private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG = AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | AudioSystem.DEVICE_OUT_LINE | Loading Loading @@ -5813,6 +5870,11 @@ public class AudioService extends IAudioService.Stub mAudioEventWakeLock.release(); break; case MSG_A2DP_ACTIVE_DEVICE_CHANGE: onBluetoothA2dpActiveDeviceChange((BluetoothA2dpDeviceInfo) msg.obj); mAudioEventWakeLock.release(); break; case MSG_DISABLE_AUDIO_FOR_UID: mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */, msg.arg2 /* uid */); Loading Loading @@ -6279,12 +6341,12 @@ public class AudioService extends IAudioService.Stub BluetoothDevice btDevice = btInfo.getBtDevice(); int a2dpCodec = btInfo.getCodec(); if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); } if (btDevice == null) { return; } if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); } String address = btDevice.getAddress(); if (!BluetoothAdapter.checkBluetoothAddress(address)) { address = ""; Loading Loading @@ -6326,6 +6388,63 @@ public class AudioService extends IAudioService.Stub } } /** message handler for MSG_A2DP_ACTIVE_DEVICE_CHANGE */ public void onBluetoothA2dpActiveDeviceChange(BluetoothA2dpDeviceInfo btInfo) { if (btInfo == null) { return; } BluetoothDevice btDevice = btInfo.getBtDevice(); int a2dpVolume = btInfo.getVolume(); int a2dpCodec = btInfo.getCodec(); if (btDevice == null) { return; } if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice); } String address = btDevice.getAddress(); if (!BluetoothAdapter.checkBluetoothAddress(address)) { address = ""; } mDeviceLogger.log(new AudioEventLogger.StringEvent( "onBluetoothA2dpActiveDeviceChange addr=" + address)); int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; synchronized (mConnectedDevices) { if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) { mDeviceLogger.log(new AudioEventLogger.StringEvent( "A2dp config change ignored")); return; } final String key = makeDeviceListKey(device, address); final DeviceListSpec deviceSpec = mConnectedDevices.get(key); if (deviceSpec == null) { return; } // Device is connected if (a2dpVolume != -1) { VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; // Convert index to internal representation in VolumeStreamState a2dpVolume = a2dpVolume * 10; streamState.setIndex(a2dpVolume, device, "onBluetoothA2dpActiveDeviceChange"); setDeviceVolume(streamState, device); } if (AudioSystem.handleDeviceConfigChange(device, address, btDevice.getName(), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) { int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC); // force A2DP device disconnection in case of error so that AudioService state is // consistent with audio policy manager state setBluetoothA2dpDeviceConnectionStateInt( btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP, false /* suppressNoisyIntent */, musicDevice, -1 /* a2dpVolume */); } } } public void avrcpSupportsAbsoluteVolume(String address, boolean support) { // address is not used for now, but may be used when multiple a2dp devices are supported synchronized (mA2dpAvrcpLock) { Loading Loading
media/java/android/media/AudioManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -4053,6 +4053,36 @@ public class AudioManager { } } /** * Indicate A2DP source or sink active device change and eventually suppress * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent. * @param device Bluetooth device connected/disconnected * @param state new connection state (BluetoothProfile.STATE_xxx) * @param profile profile for the A2DP device * (either {@link android.bluetooth.BluetoothProfile.A2DP} or * {@link android.bluetooth.BluetoothProfile.A2DP_SINK}) * @param a2dpVolume New volume for the connecting device. Does nothing if * disconnecting. Pass value -1 in case you want this field to be ignored * @param suppressNoisyIntent if true the * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent. * @return a delay in ms that the caller should wait before broadcasting * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. * {@hide} */ public int handleBluetoothA2dpActiveDeviceChange( BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { final IAudioService service = getService(); int delay = 0; try { delay = service.handleBluetoothA2dpActiveDeviceChange(device, state, profile, suppressNoisyIntent, a2dpVolume); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } return delay; } /** {@hide} */ public IRingtonePlayer getRingtonePlayer() { try { Loading
media/java/android/media/IAudioService.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,9 @@ interface IAudioService { void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device); int handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume); AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer); boolean isCameraSoundForced(); Loading
services/core/java/com/android/server/audio/AudioService.java +122 −3 Original line number Diff line number Diff line Loading @@ -270,6 +270,7 @@ public class AudioService extends IAudioService.Stub private static final int MSG_DISABLE_AUDIO_FOR_UID = 104; private static final int MSG_SET_HEARING_AID_CONNECTION_STATE = 105; private static final int MSG_BTA2DP_DOCK_TIMEOUT = 106; private static final int MSG_A2DP_ACTIVE_DEVICE_CHANGE = 107; // end of messages handled under wakelock private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; Loading Loading @@ -4673,6 +4674,7 @@ public class AudioService extends IAudioService.Stub msg == MSG_SET_HEARING_AID_CONNECTION_STATE || msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE || msg == MSG_A2DP_DEVICE_CONFIG_CHANGE || msg == MSG_A2DP_ACTIVE_DEVICE_CHANGE || msg == MSG_BTA2DP_DOCK_TIMEOUT) { if (mLastDeviceConnectMsgTime >= time) { // add a little delay to make sure messages are ordered as expected Loading Loading @@ -4892,6 +4894,61 @@ public class AudioService extends IAudioService.Stub } } /** * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int, * boolean, int) */ public int handleBluetoothA2dpActiveDeviceChange( BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { throw new IllegalArgumentException("invalid profile " + profile); } synchronized (mConnectedDevices) { if (state == BluetoothA2dp.STATE_CONNECTED) { for (int i = 0; i < mConnectedDevices.size(); i++) { DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i); if (deviceSpec.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) { continue; } // If A2DP device exists, this is either an active device change or // device config change String existingDevicekey = mConnectedDevices.keyAt(i); String deviceName = device.getName(); String address = device.getAddress(); String newDeviceKey = makeDeviceListKey( AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address); int a2dpCodec = getA2dpCodec(device); // Device not equal to existing device, active device change if (!TextUtils.equals(existingDevicekey, newDeviceKey)) { mConnectedDevices.remove(existingDevicekey); mConnectedDevices.put(newDeviceKey, new DeviceListSpec( AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName, address, a2dpCodec)); queueMsgUnderWakeLock(mAudioHandler, MSG_A2DP_ACTIVE_DEVICE_CHANGE, 0, 0, new BluetoothA2dpDeviceInfo( device, a2dpVolume, a2dpCodec), 0 /* delay */); return 0; } else { // Device config change for existing device handleBluetoothA2dpDeviceConfigChange(device); return 0; } } } } // New device connection or a device disconnect return setBluetoothA2dpDeviceConnectionStateInt( device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume); } private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG = AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | AudioSystem.DEVICE_OUT_LINE | Loading Loading @@ -5813,6 +5870,11 @@ public class AudioService extends IAudioService.Stub mAudioEventWakeLock.release(); break; case MSG_A2DP_ACTIVE_DEVICE_CHANGE: onBluetoothA2dpActiveDeviceChange((BluetoothA2dpDeviceInfo) msg.obj); mAudioEventWakeLock.release(); break; case MSG_DISABLE_AUDIO_FOR_UID: mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */, msg.arg2 /* uid */); Loading Loading @@ -6279,12 +6341,12 @@ public class AudioService extends IAudioService.Stub BluetoothDevice btDevice = btInfo.getBtDevice(); int a2dpCodec = btInfo.getCodec(); if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); } if (btDevice == null) { return; } if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); } String address = btDevice.getAddress(); if (!BluetoothAdapter.checkBluetoothAddress(address)) { address = ""; Loading Loading @@ -6326,6 +6388,63 @@ public class AudioService extends IAudioService.Stub } } /** message handler for MSG_A2DP_ACTIVE_DEVICE_CHANGE */ public void onBluetoothA2dpActiveDeviceChange(BluetoothA2dpDeviceInfo btInfo) { if (btInfo == null) { return; } BluetoothDevice btDevice = btInfo.getBtDevice(); int a2dpVolume = btInfo.getVolume(); int a2dpCodec = btInfo.getCodec(); if (btDevice == null) { return; } if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice); } String address = btDevice.getAddress(); if (!BluetoothAdapter.checkBluetoothAddress(address)) { address = ""; } mDeviceLogger.log(new AudioEventLogger.StringEvent( "onBluetoothA2dpActiveDeviceChange addr=" + address)); int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; synchronized (mConnectedDevices) { if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) { mDeviceLogger.log(new AudioEventLogger.StringEvent( "A2dp config change ignored")); return; } final String key = makeDeviceListKey(device, address); final DeviceListSpec deviceSpec = mConnectedDevices.get(key); if (deviceSpec == null) { return; } // Device is connected if (a2dpVolume != -1) { VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; // Convert index to internal representation in VolumeStreamState a2dpVolume = a2dpVolume * 10; streamState.setIndex(a2dpVolume, device, "onBluetoothA2dpActiveDeviceChange"); setDeviceVolume(streamState, device); } if (AudioSystem.handleDeviceConfigChange(device, address, btDevice.getName(), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) { int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC); // force A2DP device disconnection in case of error so that AudioService state is // consistent with audio policy manager state setBluetoothA2dpDeviceConnectionStateInt( btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP, false /* suppressNoisyIntent */, musicDevice, -1 /* a2dpVolume */); } } } public void avrcpSupportsAbsoluteVolume(String address, boolean support) { // address is not used for now, but may be used when multiple a2dp devices are supported synchronized (mA2dpAvrcpLock) { Loading