Loading android/app/src/com/android/bluetooth/btservice/AudioRoutingManager.java +82 −67 Original line number Original line Diff line number Diff line Loading @@ -334,6 +334,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { return; return; } } mHearingAidConnectedDevices.add(device); mHearingAidConnectedDevices.add(device); } // New connected device: select it as active // New connected device: select it as active if (setHearingAidActiveDevice(device)) { if (setHearingAidActiveDevice(device)) { setA2dpActiveDevice(null, true); setA2dpActiveDevice(null, true); Loading @@ -341,7 +342,6 @@ public class AudioRoutingManager extends ActiveDeviceManager { setLeAudioActiveDevice(null, true); setLeAudioActiveDevice(null, true); } } } } } private void handleLeAudioConnected(BluetoothDevice device) { private void handleLeAudioConnected(BluetoothDevice device) { synchronized (mLock) { synchronized (mLock) { Loading Loading @@ -675,13 +675,13 @@ public class AudioRoutingManager extends ActiveDeviceManager { hearingAidService.getConnectedPeerDevices(hiSyncId)); hearingAidService.getConnectedPeerDevices(hiSyncId)); } } } } } if (device != null) { if (device != null) { setA2dpActiveDevice(null, true); setA2dpActiveDevice(null, true); setHfpActiveDevice(null); setHfpActiveDevice(null); setLeAudioActiveDevice(null, true); setLeAudioActiveDevice(null, true); } } } } } private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) { private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) { synchronized (mLock) { synchronized (mLock) { Loading Loading @@ -854,14 +854,15 @@ public class AudioRoutingManager extends ActiveDeviceManager { @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) private boolean setHfpActiveDevice(BluetoothDevice device) { private boolean setHfpActiveDevice(BluetoothDevice device) { synchronized (mLock) { if (DBG) { if (DBG) { Log.d(TAG, "setHfpActiveDevice(" + device + ")"); Log.d(TAG, "setHfpActiveDevice(" + device + ")"); } } synchronized (mLock) { if (mPendingActiveDevice != null) { if (mPendingActiveDevice != null) { mHandler.removeCallbacksAndMessages(mPendingActiveDevice); mHandler.removeCallbacksAndMessages(mPendingActiveDevice); mPendingActiveDevice = null; mPendingActiveDevice = null; } } } final HeadsetService headsetService = mFactory.getHeadsetService(); final HeadsetService headsetService = mFactory.getHeadsetService(); if (headsetService == null) { if (headsetService == null) { return false; return false; Loading @@ -875,6 +876,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { if (!headsetService.setActiveDevice(device)) { if (!headsetService.setActiveDevice(device)) { return false; return false; } } synchronized (mLock) { mHfpActiveDevice = device; mHfpActiveDevice = device; } } return true; return true; Loading Loading @@ -938,7 +940,6 @@ public class AudioRoutingManager extends ActiveDeviceManager { + ")" + ")" + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : "")); + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : "")); } } synchronized (mLock) { final LeAudioService leAudioService = mFactory.getLeAudioService(); final LeAudioService leAudioService = mFactory.getLeAudioService(); if (leAudioService == null) { if (leAudioService == null) { return false; return false; Loading @@ -954,6 +955,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { return false; return false; } } synchronized (mLock) { mLeAudioActiveDevice = device; mLeAudioActiveDevice = device; if (device == null) { if (device == null) { mLeHearingAidActiveDevice = null; mLeHearingAidActiveDevice = null; Loading Loading @@ -1025,45 +1027,33 @@ public class AudioRoutingManager extends ActiveDeviceManager { } } } } A2dpService a2dpService = mFactory.getA2dpService(); List<BluetoothDevice> hfpFallbackCandidates = removeWatchDevices(mHfpConnectedDevices); BluetoothDevice a2dpFallbackDevice = null; List<BluetoothDevice> fallbackCandidates = new ArrayList<>(); if (a2dpService != null) { fallbackCandidates.addAll(mLeAudioConnectedDevices); a2dpFallbackDevice = a2dpService.getFallbackDevice(); } HeadsetService headsetService = mFactory.getHeadsetService(); HeadsetService headsetService = mFactory.getHeadsetService(); BluetoothDevice headsetFallbackDevice = null; if (headsetService != null) { headsetFallbackDevice = headsetService.getFallbackDevice(); } List<BluetoothDevice> connectedDevices = new ArrayList<>(); connectedDevices.addAll(mLeAudioConnectedDevices); switch (mAudioManager.getMode()) { switch (mAudioManager.getMode()) { case AudioManager.MODE_NORMAL: case AudioManager.MODE_NORMAL: if (a2dpFallbackDevice != null) { fallbackCandidates.addAll(mA2dpConnectedDevices); connectedDevices.add(a2dpFallbackDevice); } break; break; case AudioManager.MODE_RINGTONE: case AudioManager.MODE_RINGTONE: if (headsetFallbackDevice != null && headsetService.isInbandRingingEnabled()) { if (headsetService.isInbandRingingEnabled()) { connectedDevices.add(headsetFallbackDevice); fallbackCandidates.addAll(hfpFallbackCandidates); } } break; break; default: default: if (headsetFallbackDevice != null) { fallbackCandidates.addAll(hfpFallbackCandidates); connectedDevices.add(headsetFallbackDevice); } } } BluetoothDevice device = BluetoothDevice device = mDbManager.getMostRecentlyConnectedDevicesInList(connectedDevices); mDbManager.getMostRecentlyConnectedDevicesInList(fallbackCandidates); if (device != null) { if (device != null) { if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { if (Objects.equals(a2dpFallbackDevice, device)) { if (mA2dpConnectedDevices.contains(device)) { if (DBG) { if (DBG) { Log.d(TAG, "Found an A2DP fallback device: " + device); Log.d(TAG, "Found an A2DP fallback device: " + device); } } setA2dpActiveDevice(device); setA2dpActiveDevice(device); if (Objects.equals(headsetFallbackDevice, device)) { if (hfpFallbackCandidates.contains(device)) { setHfpActiveDevice(device); setHfpActiveDevice(device); } else { } else { setHfpActiveDevice(null); setHfpActiveDevice(null); Loading @@ -1089,13 +1079,13 @@ public class AudioRoutingManager extends ActiveDeviceManager { setHearingAidActiveDevice(null, true); setHearingAidActiveDevice(null, true); } } } else { } else { if (Objects.equals(headsetFallbackDevice, device)) { if (hfpFallbackCandidates.contains(device)) { if (DBG) { if (DBG) { Log.d(TAG, "Found a HFP fallback device: " + device); Log.d(TAG, "Found a HFP fallback device: " + device); } } setHfpActiveDevice(device); setHfpActiveDevice(device); if (Objects.equals(a2dpFallbackDevice, device)) { if (mA2dpConnectedDevices.contains(device)) { setA2dpActiveDevice(a2dpFallbackDevice); setA2dpActiveDevice(device); } else { } else { setA2dpActiveDevice(null, true); setA2dpActiveDevice(null, true); } } Loading Loading @@ -1144,6 +1134,31 @@ public class AudioRoutingManager extends ActiveDeviceManager { } } } } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) List<BluetoothDevice> removeWatchDevices(List<BluetoothDevice> devices) { List<BluetoothDevice> fallbackCandidates; synchronized (mLock) { fallbackCandidates = new ArrayList<>(devices); } List<BluetoothDevice> uninterestedCandidates = new ArrayList<>(); for (BluetoothDevice device : fallbackCandidates) { byte[] deviceType = mDbManager.getCustomMeta(device, BluetoothDevice.METADATA_DEVICE_TYPE); BluetoothClass deviceClass = device.getBluetoothClass(); if ((deviceClass != null && deviceClass.getMajorDeviceClass() == BluetoothClass.Device.WEARABLE_WRIST_WATCH) || (deviceType != null && BluetoothDevice.DEVICE_TYPE_WATCH.equals(new String(deviceType)))) { uninterestedCandidates.add(device); } } for (BluetoothDevice device : uninterestedCandidates) { fallbackCandidates.remove(device); } return fallbackCandidates; } @VisibleForTesting @VisibleForTesting BluetoothDevice getA2dpActiveDevice() { BluetoothDevice getA2dpActiveDevice() { synchronized (mLock) { synchronized (mLock) { Loading android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java +0 −26 Original line number Original line Diff line number Diff line Loading @@ -62,7 +62,6 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Objects; @MediumTest @MediumTest @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) Loading Loading @@ -146,31 +145,6 @@ public class AudioRoutingManagerTest { when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId); when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId); when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId)) when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId)) .thenReturn(connectedHearingAidDevices); .thenReturn(connectedHearingAidDevices); when(mA2dpService.getFallbackDevice()) .thenAnswer( invocation -> { if (!mDeviceConnectionStack.isEmpty() && Objects.equals( mA2dpDevice, mDeviceConnectionStack.get( mDeviceConnectionStack.size() - 1))) { return mA2dpDevice; } return null; }); when(mHeadsetService.getFallbackDevice()) .thenAnswer( invocation -> { if (!mDeviceConnectionStack.isEmpty() && Objects.equals( mHeadsetDevice, mDeviceConnectionStack.get( mDeviceConnectionStack.size() - 1))) { return mHeadsetDevice; } return null; }); } } @After @After Loading Loading
android/app/src/com/android/bluetooth/btservice/AudioRoutingManager.java +82 −67 Original line number Original line Diff line number Diff line Loading @@ -334,6 +334,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { return; return; } } mHearingAidConnectedDevices.add(device); mHearingAidConnectedDevices.add(device); } // New connected device: select it as active // New connected device: select it as active if (setHearingAidActiveDevice(device)) { if (setHearingAidActiveDevice(device)) { setA2dpActiveDevice(null, true); setA2dpActiveDevice(null, true); Loading @@ -341,7 +342,6 @@ public class AudioRoutingManager extends ActiveDeviceManager { setLeAudioActiveDevice(null, true); setLeAudioActiveDevice(null, true); } } } } } private void handleLeAudioConnected(BluetoothDevice device) { private void handleLeAudioConnected(BluetoothDevice device) { synchronized (mLock) { synchronized (mLock) { Loading Loading @@ -675,13 +675,13 @@ public class AudioRoutingManager extends ActiveDeviceManager { hearingAidService.getConnectedPeerDevices(hiSyncId)); hearingAidService.getConnectedPeerDevices(hiSyncId)); } } } } } if (device != null) { if (device != null) { setA2dpActiveDevice(null, true); setA2dpActiveDevice(null, true); setHfpActiveDevice(null); setHfpActiveDevice(null); setLeAudioActiveDevice(null, true); setLeAudioActiveDevice(null, true); } } } } } private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) { private void handleLeAudioActiveDeviceChanged(BluetoothDevice device) { synchronized (mLock) { synchronized (mLock) { Loading Loading @@ -854,14 +854,15 @@ public class AudioRoutingManager extends ActiveDeviceManager { @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) private boolean setHfpActiveDevice(BluetoothDevice device) { private boolean setHfpActiveDevice(BluetoothDevice device) { synchronized (mLock) { if (DBG) { if (DBG) { Log.d(TAG, "setHfpActiveDevice(" + device + ")"); Log.d(TAG, "setHfpActiveDevice(" + device + ")"); } } synchronized (mLock) { if (mPendingActiveDevice != null) { if (mPendingActiveDevice != null) { mHandler.removeCallbacksAndMessages(mPendingActiveDevice); mHandler.removeCallbacksAndMessages(mPendingActiveDevice); mPendingActiveDevice = null; mPendingActiveDevice = null; } } } final HeadsetService headsetService = mFactory.getHeadsetService(); final HeadsetService headsetService = mFactory.getHeadsetService(); if (headsetService == null) { if (headsetService == null) { return false; return false; Loading @@ -875,6 +876,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { if (!headsetService.setActiveDevice(device)) { if (!headsetService.setActiveDevice(device)) { return false; return false; } } synchronized (mLock) { mHfpActiveDevice = device; mHfpActiveDevice = device; } } return true; return true; Loading Loading @@ -938,7 +940,6 @@ public class AudioRoutingManager extends ActiveDeviceManager { + ")" + ")" + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : "")); + (device == null ? " hasFallbackDevice=" + hasFallbackDevice : "")); } } synchronized (mLock) { final LeAudioService leAudioService = mFactory.getLeAudioService(); final LeAudioService leAudioService = mFactory.getLeAudioService(); if (leAudioService == null) { if (leAudioService == null) { return false; return false; Loading @@ -954,6 +955,7 @@ public class AudioRoutingManager extends ActiveDeviceManager { return false; return false; } } synchronized (mLock) { mLeAudioActiveDevice = device; mLeAudioActiveDevice = device; if (device == null) { if (device == null) { mLeHearingAidActiveDevice = null; mLeHearingAidActiveDevice = null; Loading Loading @@ -1025,45 +1027,33 @@ public class AudioRoutingManager extends ActiveDeviceManager { } } } } A2dpService a2dpService = mFactory.getA2dpService(); List<BluetoothDevice> hfpFallbackCandidates = removeWatchDevices(mHfpConnectedDevices); BluetoothDevice a2dpFallbackDevice = null; List<BluetoothDevice> fallbackCandidates = new ArrayList<>(); if (a2dpService != null) { fallbackCandidates.addAll(mLeAudioConnectedDevices); a2dpFallbackDevice = a2dpService.getFallbackDevice(); } HeadsetService headsetService = mFactory.getHeadsetService(); HeadsetService headsetService = mFactory.getHeadsetService(); BluetoothDevice headsetFallbackDevice = null; if (headsetService != null) { headsetFallbackDevice = headsetService.getFallbackDevice(); } List<BluetoothDevice> connectedDevices = new ArrayList<>(); connectedDevices.addAll(mLeAudioConnectedDevices); switch (mAudioManager.getMode()) { switch (mAudioManager.getMode()) { case AudioManager.MODE_NORMAL: case AudioManager.MODE_NORMAL: if (a2dpFallbackDevice != null) { fallbackCandidates.addAll(mA2dpConnectedDevices); connectedDevices.add(a2dpFallbackDevice); } break; break; case AudioManager.MODE_RINGTONE: case AudioManager.MODE_RINGTONE: if (headsetFallbackDevice != null && headsetService.isInbandRingingEnabled()) { if (headsetService.isInbandRingingEnabled()) { connectedDevices.add(headsetFallbackDevice); fallbackCandidates.addAll(hfpFallbackCandidates); } } break; break; default: default: if (headsetFallbackDevice != null) { fallbackCandidates.addAll(hfpFallbackCandidates); connectedDevices.add(headsetFallbackDevice); } } } BluetoothDevice device = BluetoothDevice device = mDbManager.getMostRecentlyConnectedDevicesInList(connectedDevices); mDbManager.getMostRecentlyConnectedDevicesInList(fallbackCandidates); if (device != null) { if (device != null) { if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) { if (Objects.equals(a2dpFallbackDevice, device)) { if (mA2dpConnectedDevices.contains(device)) { if (DBG) { if (DBG) { Log.d(TAG, "Found an A2DP fallback device: " + device); Log.d(TAG, "Found an A2DP fallback device: " + device); } } setA2dpActiveDevice(device); setA2dpActiveDevice(device); if (Objects.equals(headsetFallbackDevice, device)) { if (hfpFallbackCandidates.contains(device)) { setHfpActiveDevice(device); setHfpActiveDevice(device); } else { } else { setHfpActiveDevice(null); setHfpActiveDevice(null); Loading @@ -1089,13 +1079,13 @@ public class AudioRoutingManager extends ActiveDeviceManager { setHearingAidActiveDevice(null, true); setHearingAidActiveDevice(null, true); } } } else { } else { if (Objects.equals(headsetFallbackDevice, device)) { if (hfpFallbackCandidates.contains(device)) { if (DBG) { if (DBG) { Log.d(TAG, "Found a HFP fallback device: " + device); Log.d(TAG, "Found a HFP fallback device: " + device); } } setHfpActiveDevice(device); setHfpActiveDevice(device); if (Objects.equals(a2dpFallbackDevice, device)) { if (mA2dpConnectedDevices.contains(device)) { setA2dpActiveDevice(a2dpFallbackDevice); setA2dpActiveDevice(device); } else { } else { setA2dpActiveDevice(null, true); setA2dpActiveDevice(null, true); } } Loading Loading @@ -1144,6 +1134,31 @@ public class AudioRoutingManager extends ActiveDeviceManager { } } } } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) List<BluetoothDevice> removeWatchDevices(List<BluetoothDevice> devices) { List<BluetoothDevice> fallbackCandidates; synchronized (mLock) { fallbackCandidates = new ArrayList<>(devices); } List<BluetoothDevice> uninterestedCandidates = new ArrayList<>(); for (BluetoothDevice device : fallbackCandidates) { byte[] deviceType = mDbManager.getCustomMeta(device, BluetoothDevice.METADATA_DEVICE_TYPE); BluetoothClass deviceClass = device.getBluetoothClass(); if ((deviceClass != null && deviceClass.getMajorDeviceClass() == BluetoothClass.Device.WEARABLE_WRIST_WATCH) || (deviceType != null && BluetoothDevice.DEVICE_TYPE_WATCH.equals(new String(deviceType)))) { uninterestedCandidates.add(device); } } for (BluetoothDevice device : uninterestedCandidates) { fallbackCandidates.remove(device); } return fallbackCandidates; } @VisibleForTesting @VisibleForTesting BluetoothDevice getA2dpActiveDevice() { BluetoothDevice getA2dpActiveDevice() { synchronized (mLock) { synchronized (mLock) { Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java +0 −26 Original line number Original line Diff line number Diff line Loading @@ -62,7 +62,6 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Objects; @MediumTest @MediumTest @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) Loading Loading @@ -146,31 +145,6 @@ public class AudioRoutingManagerTest { when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId); when(mHearingAidService.getHiSyncId(mHearingAidDevice)).thenReturn(mHearingAidHiSyncId); when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId)) when(mHearingAidService.getConnectedPeerDevices(mHearingAidHiSyncId)) .thenReturn(connectedHearingAidDevices); .thenReturn(connectedHearingAidDevices); when(mA2dpService.getFallbackDevice()) .thenAnswer( invocation -> { if (!mDeviceConnectionStack.isEmpty() && Objects.equals( mA2dpDevice, mDeviceConnectionStack.get( mDeviceConnectionStack.size() - 1))) { return mA2dpDevice; } return null; }); when(mHeadsetService.getFallbackDevice()) .thenAnswer( invocation -> { if (!mDeviceConnectionStack.isEmpty() && Objects.equals( mHeadsetDevice, mDeviceConnectionStack.get( mDeviceConnectionStack.size() - 1))) { return mHeadsetDevice; } return null; }); } } @After @After Loading