Loading android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +15 −115 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.RejectedExecutionException; /** * The active device manager is responsible for keeping track of the Loading Loading @@ -131,18 +130,15 @@ class ActiveDeviceManager { private Handler mHandler = null; private final AudioManager mAudioManager; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; private final AudioManagerOnModeChangedListener mAudioManagerOnModeChangedListener; private final List<BluetoothDevice> mA2dpConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mHfpConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mHearingAidConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mLeAudioConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mLeHearingAidConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mPendingLeHearingAidActiveDevice = new ArrayList<>(); private List<BluetoothDevice> mPendingLeHearingAidActiveDevice = new ArrayList<>(); private BluetoothDevice mA2dpActiveDevice = null; private BluetoothDevice mPendingA2dpActiveDevice = null; private BluetoothDevice mHfpActiveDevice = null; private BluetoothDevice mPendingHfpActiveDevice = null; private BluetoothDevice mHearingAidActiveDevice = null; private BluetoothDevice mLeAudioActiveDevice = null; private BluetoothDevice mLeHearingAidActiveDevice = null; Loading Loading @@ -249,43 +245,16 @@ class ActiveDeviceManager { if (mA2dpConnectedDevices.contains(device)) { break; // The device is already connected } // New connected A2DP device mA2dpConnectedDevices.add(device); if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) { // Lazy active A2DP if it is not being used. // This will prevent the deactivation of LE audio // earlier than the activation of HFP. switch (mAudioManager.getMode()) { case AudioManager.MODE_NORMAL: break; case AudioManager.MODE_RINGTONE: { HeadsetService headsetService = mFactory.getHeadsetService(); if (mHfpActiveDevice == null && headsetService != null && headsetService.isInbandRingingEnabled()) { mPendingA2dpActiveDevice = device; } break; } case AudioManager.MODE_IN_CALL: case AudioManager.MODE_IN_COMMUNICATION: case AudioManager.MODE_CALL_SCREENING: case AudioManager.MODE_CALL_REDIRECT: case AudioManager.MODE_COMMUNICATION_REDIRECT: { if (mHfpActiveDevice == null) { mPendingA2dpActiveDevice = device; } } } if (mPendingA2dpActiveDevice == null) { // select the device as active if not lazy active // New connected device: select it as active setA2dpActiveDevice(device); setLeAudioActiveDevice(null); } } break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // A2DP device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_A2DP_ACTION_CONNECTION_STATE_CHANGED): " Loading Loading @@ -342,37 +311,16 @@ class ActiveDeviceManager { if (mHfpConnectedDevices.contains(device)) { break; // The device is already connected } // New connected HFP device. mHfpConnectedDevices.add(device); if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) { // Lazy active HFP if it is not being used. // This will prevent the deactivation of LE audio // earlier than the activation of A2DP. switch (mAudioManager.getMode()) { case AudioManager.MODE_NORMAL: if (mA2dpActiveDevice == null) { mPendingHfpActiveDevice = device; } break; case AudioManager.MODE_RINGTONE: { HeadsetService headsetService = mFactory.getHeadsetService(); if (headsetService == null || !headsetService.isInbandRingingEnabled()) { mPendingHfpActiveDevice = device; } break; } } if (mPendingHfpActiveDevice == null) { // select the device as active if not lazy active // New connected device: select it as active setHfpActiveDevice(device); setLeAudioActiveDevice(null); } } break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // HFP device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED): " Loading Loading @@ -429,7 +377,7 @@ class ActiveDeviceManager { break; // The device is already connected } mHearingAidConnectedDevices.add(device); // New connected hearing aid device: select it as active // New connected device: select it as active setHearingAidActiveDevice(device); setA2dpActiveDevice(null); setHfpActiveDevice(null); Loading @@ -437,7 +385,7 @@ class ActiveDeviceManager { break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // Hearing aid device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_HEARING_AID_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); Loading Loading @@ -493,7 +441,7 @@ class ActiveDeviceManager { mLeAudioConnectedDevices.add(device); if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null && mPendingLeHearingAidActiveDevice.isEmpty()) { // New connected LE audio device: select it as active // New connected device: select it as active setLeAudioActiveDevice(device); setA2dpActiveDevice(null); setHfpActiveDevice(null); Loading @@ -506,7 +454,7 @@ class ActiveDeviceManager { break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // LE audio device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); Loading Loading @@ -569,7 +517,7 @@ class ActiveDeviceManager { } else if (Objects.equals(mLeAudioActiveDevice, device)) { mLeHearingAidActiveDevice = device; } else { // New connected LE hearing aid device: select it as active // New connected device: select it as active setLeHearingAidActiveDevice(device); setHearingAidActiveDevice(null); setA2dpActiveDevice(null); Loading @@ -578,7 +526,7 @@ class ActiveDeviceManager { break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // LE hearing aid device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_HAP_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); Loading Loading @@ -616,40 +564,6 @@ class ActiveDeviceManager { } } private class AudioManagerOnModeChangedListener implements AudioManager.OnModeChangedListener { public void onModeChanged(int mode) { switch (mode) { case AudioManager.MODE_NORMAL: { if (mPendingA2dpActiveDevice != null) { setA2dpActiveDevice(mPendingA2dpActiveDevice); setLeAudioActiveDevice(null); } break; } case AudioManager.MODE_RINGTONE: { final HeadsetService headsetService = mFactory.getHeadsetService(); if (headsetService != null && headsetService.isInbandRingingEnabled() && mPendingHfpActiveDevice != null) { setHfpActiveDevice(mPendingHfpActiveDevice); setLeAudioActiveDevice(null); } break; } case AudioManager.MODE_IN_CALL: case AudioManager.MODE_IN_COMMUNICATION: case AudioManager.MODE_CALL_SCREENING: case AudioManager.MODE_CALL_REDIRECT: case AudioManager.MODE_COMMUNICATION_REDIRECT: { if (mPendingHfpActiveDevice != null) { setHfpActiveDevice(mPendingHfpActiveDevice); setLeAudioActiveDevice(null); } break; } } } } /** Notifications of audio device connection and disconnection events. */ @SuppressLint("AndroidFrameworkRequiresPermission") private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { Loading Loading @@ -696,7 +610,6 @@ class ActiveDeviceManager { mFactory = factory; mAudioManager = service.getSystemService(AudioManager.class); mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); mAudioManagerOnModeChangedListener = new AudioManagerOnModeChangedListener(); } void start() { Loading @@ -723,11 +636,6 @@ class ActiveDeviceManager { mAdapterService.registerReceiver(mReceiver, filter); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); mAudioManager.addOnModeChangedListener(command -> { if (!mHandler.post(command)) { throw new RejectedExecutionException(mHandler + " is shutting down"); } }, mAudioManagerOnModeChangedListener); } void cleanup() { Loading Loading @@ -770,10 +678,6 @@ class ActiveDeviceManager { return; } mA2dpActiveDevice = device; mPendingA2dpActiveDevice = null; if (mPendingHfpActiveDevice != null) { setHfpActiveDevice(mPendingHfpActiveDevice); } } @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) Loading @@ -789,10 +693,6 @@ class ActiveDeviceManager { return; } mHfpActiveDevice = device; mPendingHfpActiveDevice = null; if (mPendingA2dpActiveDevice != null) { setA2dpActiveDevice(mPendingA2dpActiveDevice); } } private void setHearingAidActiveDevice(BluetoothDevice device) { Loading android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +1 −9 Original line number Diff line number Diff line Loading @@ -244,8 +244,6 @@ public class ActiveDeviceManagerTest { */ @Test public void onlyHeadsetConnected_setHeadsetActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); } Loading @@ -255,8 +253,6 @@ public class ActiveDeviceManagerTest { */ @Test public void secondHeadsetConnected_setSecondHeadsetActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); Loading @@ -269,8 +265,6 @@ public class ActiveDeviceManagerTest { */ @Test public void lastHeadsetDisconnected_clearHeadsetActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); Loading @@ -283,8 +277,6 @@ public class ActiveDeviceManagerTest { */ @Test public void headsetActiveDeviceSelected_setActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); Loading Loading @@ -521,7 +513,7 @@ public class ActiveDeviceManagerTest { public void leAudioActive_setHeadsetActiveExplicitly() { Assume.assumeTrue("Ignore test when LeAudioService is not enabled", LeAudioService.isEnabled()); when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); leAudioActiveDeviceChanged(mLeAudioDevice); headsetConnected(mA2dpHeadsetDevice); headsetActiveDeviceChanged(mA2dpHeadsetDevice); Loading Loading
android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +15 −115 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.RejectedExecutionException; /** * The active device manager is responsible for keeping track of the Loading Loading @@ -131,18 +130,15 @@ class ActiveDeviceManager { private Handler mHandler = null; private final AudioManager mAudioManager; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; private final AudioManagerOnModeChangedListener mAudioManagerOnModeChangedListener; private final List<BluetoothDevice> mA2dpConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mHfpConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mHearingAidConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mLeAudioConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mLeHearingAidConnectedDevices = new ArrayList<>(); private final List<BluetoothDevice> mPendingLeHearingAidActiveDevice = new ArrayList<>(); private List<BluetoothDevice> mPendingLeHearingAidActiveDevice = new ArrayList<>(); private BluetoothDevice mA2dpActiveDevice = null; private BluetoothDevice mPendingA2dpActiveDevice = null; private BluetoothDevice mHfpActiveDevice = null; private BluetoothDevice mPendingHfpActiveDevice = null; private BluetoothDevice mHearingAidActiveDevice = null; private BluetoothDevice mLeAudioActiveDevice = null; private BluetoothDevice mLeHearingAidActiveDevice = null; Loading Loading @@ -249,43 +245,16 @@ class ActiveDeviceManager { if (mA2dpConnectedDevices.contains(device)) { break; // The device is already connected } // New connected A2DP device mA2dpConnectedDevices.add(device); if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) { // Lazy active A2DP if it is not being used. // This will prevent the deactivation of LE audio // earlier than the activation of HFP. switch (mAudioManager.getMode()) { case AudioManager.MODE_NORMAL: break; case AudioManager.MODE_RINGTONE: { HeadsetService headsetService = mFactory.getHeadsetService(); if (mHfpActiveDevice == null && headsetService != null && headsetService.isInbandRingingEnabled()) { mPendingA2dpActiveDevice = device; } break; } case AudioManager.MODE_IN_CALL: case AudioManager.MODE_IN_COMMUNICATION: case AudioManager.MODE_CALL_SCREENING: case AudioManager.MODE_CALL_REDIRECT: case AudioManager.MODE_COMMUNICATION_REDIRECT: { if (mHfpActiveDevice == null) { mPendingA2dpActiveDevice = device; } } } if (mPendingA2dpActiveDevice == null) { // select the device as active if not lazy active // New connected device: select it as active setA2dpActiveDevice(device); setLeAudioActiveDevice(null); } } break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // A2DP device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_A2DP_ACTION_CONNECTION_STATE_CHANGED): " Loading Loading @@ -342,37 +311,16 @@ class ActiveDeviceManager { if (mHfpConnectedDevices.contains(device)) { break; // The device is already connected } // New connected HFP device. mHfpConnectedDevices.add(device); if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null) { // Lazy active HFP if it is not being used. // This will prevent the deactivation of LE audio // earlier than the activation of A2DP. switch (mAudioManager.getMode()) { case AudioManager.MODE_NORMAL: if (mA2dpActiveDevice == null) { mPendingHfpActiveDevice = device; } break; case AudioManager.MODE_RINGTONE: { HeadsetService headsetService = mFactory.getHeadsetService(); if (headsetService == null || !headsetService.isInbandRingingEnabled()) { mPendingHfpActiveDevice = device; } break; } } if (mPendingHfpActiveDevice == null) { // select the device as active if not lazy active // New connected device: select it as active setHfpActiveDevice(device); setLeAudioActiveDevice(null); } } break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // HFP device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_HFP_ACTION_CONNECTION_STATE_CHANGED): " Loading Loading @@ -429,7 +377,7 @@ class ActiveDeviceManager { break; // The device is already connected } mHearingAidConnectedDevices.add(device); // New connected hearing aid device: select it as active // New connected device: select it as active setHearingAidActiveDevice(device); setA2dpActiveDevice(null); setHfpActiveDevice(null); Loading @@ -437,7 +385,7 @@ class ActiveDeviceManager { break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // Hearing aid device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_HEARING_AID_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); Loading Loading @@ -493,7 +441,7 @@ class ActiveDeviceManager { mLeAudioConnectedDevices.add(device); if (mHearingAidActiveDevice == null && mLeHearingAidActiveDevice == null && mPendingLeHearingAidActiveDevice.isEmpty()) { // New connected LE audio device: select it as active // New connected device: select it as active setLeAudioActiveDevice(device); setA2dpActiveDevice(null); setHfpActiveDevice(null); Loading @@ -506,7 +454,7 @@ class ActiveDeviceManager { break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // LE audio device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_LE_AUDIO_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); Loading Loading @@ -569,7 +517,7 @@ class ActiveDeviceManager { } else if (Objects.equals(mLeAudioActiveDevice, device)) { mLeHearingAidActiveDevice = device; } else { // New connected LE hearing aid device: select it as active // New connected device: select it as active setLeHearingAidActiveDevice(device); setHearingAidActiveDevice(null); setA2dpActiveDevice(null); Loading @@ -578,7 +526,7 @@ class ActiveDeviceManager { break; } if (prevState == BluetoothProfile.STATE_CONNECTED) { // LE hearing aid device disconnected // Device disconnected if (DBG) { Log.d(TAG, "handleMessage(MESSAGE_HAP_ACTION_CONNECTION_STATE" + "_CHANGED): device " + device + " disconnected"); Loading Loading @@ -616,40 +564,6 @@ class ActiveDeviceManager { } } private class AudioManagerOnModeChangedListener implements AudioManager.OnModeChangedListener { public void onModeChanged(int mode) { switch (mode) { case AudioManager.MODE_NORMAL: { if (mPendingA2dpActiveDevice != null) { setA2dpActiveDevice(mPendingA2dpActiveDevice); setLeAudioActiveDevice(null); } break; } case AudioManager.MODE_RINGTONE: { final HeadsetService headsetService = mFactory.getHeadsetService(); if (headsetService != null && headsetService.isInbandRingingEnabled() && mPendingHfpActiveDevice != null) { setHfpActiveDevice(mPendingHfpActiveDevice); setLeAudioActiveDevice(null); } break; } case AudioManager.MODE_IN_CALL: case AudioManager.MODE_IN_COMMUNICATION: case AudioManager.MODE_CALL_SCREENING: case AudioManager.MODE_CALL_REDIRECT: case AudioManager.MODE_COMMUNICATION_REDIRECT: { if (mPendingHfpActiveDevice != null) { setHfpActiveDevice(mPendingHfpActiveDevice); setLeAudioActiveDevice(null); } break; } } } } /** Notifications of audio device connection and disconnection events. */ @SuppressLint("AndroidFrameworkRequiresPermission") private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { Loading Loading @@ -696,7 +610,6 @@ class ActiveDeviceManager { mFactory = factory; mAudioManager = service.getSystemService(AudioManager.class); mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); mAudioManagerOnModeChangedListener = new AudioManagerOnModeChangedListener(); } void start() { Loading @@ -723,11 +636,6 @@ class ActiveDeviceManager { mAdapterService.registerReceiver(mReceiver, filter); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); mAudioManager.addOnModeChangedListener(command -> { if (!mHandler.post(command)) { throw new RejectedExecutionException(mHandler + " is shutting down"); } }, mAudioManagerOnModeChangedListener); } void cleanup() { Loading Loading @@ -770,10 +678,6 @@ class ActiveDeviceManager { return; } mA2dpActiveDevice = device; mPendingA2dpActiveDevice = null; if (mPendingHfpActiveDevice != null) { setHfpActiveDevice(mPendingHfpActiveDevice); } } @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) Loading @@ -789,10 +693,6 @@ class ActiveDeviceManager { return; } mHfpActiveDevice = device; mPendingHfpActiveDevice = null; if (mPendingA2dpActiveDevice != null) { setA2dpActiveDevice(mPendingA2dpActiveDevice); } } private void setHearingAidActiveDevice(BluetoothDevice device) { Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +1 −9 Original line number Diff line number Diff line Loading @@ -244,8 +244,6 @@ public class ActiveDeviceManagerTest { */ @Test public void onlyHeadsetConnected_setHeadsetActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); } Loading @@ -255,8 +253,6 @@ public class ActiveDeviceManagerTest { */ @Test public void secondHeadsetConnected_setSecondHeadsetActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); Loading @@ -269,8 +265,6 @@ public class ActiveDeviceManagerTest { */ @Test public void lastHeadsetDisconnected_clearHeadsetActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); Loading @@ -283,8 +277,6 @@ public class ActiveDeviceManagerTest { */ @Test public void headsetActiveDeviceSelected_setActive() { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); headsetConnected(mHeadsetDevice); verify(mHeadsetService, timeout(TIMEOUT_MS)).setActiveDevice(mHeadsetDevice); Loading Loading @@ -521,7 +513,7 @@ public class ActiveDeviceManagerTest { public void leAudioActive_setHeadsetActiveExplicitly() { Assume.assumeTrue("Ignore test when LeAudioService is not enabled", LeAudioService.isEnabled()); when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); leAudioActiveDeviceChanged(mLeAudioDevice); headsetConnected(mA2dpHeadsetDevice); headsetActiveDeviceChanged(mA2dpHeadsetDevice); Loading