Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +27 −6 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ public class BluetoothEventManager { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final LocalBluetoothAdapter mLocalAdapter; private final LocalBluetoothManager mBtManager; private final CachedBluetoothDeviceManager mDeviceManager; private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter; private final Map<String, Handler> mHandlerMap; Loading @@ -80,10 +81,15 @@ public class BluetoothEventManager { * userHandle passed in is {@code null}, we register event receiver for the * {@code context.getUser()} handle. */ BluetoothEventManager(LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, Context context, android.os.Handler handler, @Nullable UserHandle userHandle) { BluetoothEventManager( LocalBluetoothAdapter adapter, LocalBluetoothManager btManager, CachedBluetoothDeviceManager deviceManager, Context context, android.os.Handler handler, @Nullable UserHandle userHandle) { mLocalAdapter = adapter; mBtManager = btManager; mDeviceManager = deviceManager; mAdapterIntentFilter = new IntentFilter(); mProfileIntentFilter = new IntentFilter(); Loading Loading @@ -210,11 +216,27 @@ public class BluetoothEventManager { } } void dispatchProfileConnectionStateChanged(@NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) { void dispatchProfileConnectionStateChanged( @NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) { for (BluetoothCallback callback : mCallbacks) { callback.onProfileConnectionStateChanged(device, state, bluetoothProfile); } // Trigger updateFallbackActiveDeviceIfNeeded when ASSISTANT profile disconnected when // audio sharing is enabled. if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT && state == BluetoothAdapter.STATE_DISCONNECTED && BluetoothUtils.isAudioSharingEnabled()) { LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); if (profileManager != null && profileManager.getLeAudioBroadcastProfile() != null && profileManager.getLeAudioBroadcastProfile().isProfileReady() && profileManager.getLeAudioBroadcastAssistantProfile() != null && profileManager.getLeAudioBroadcastAssistantProfile().isProfileReady()) { Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, ASSISTANT profile disconnected"); profileManager.getLeAudioBroadcastProfile().updateFallbackActiveDeviceIfNeeded(); } } } private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { Loading Loading @@ -536,7 +558,6 @@ public class BluetoothEventManager { default: Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action); return; } dispatchAclStateChanged(activeDevice, state); } Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java +13 −6 Original line number Diff line number Diff line Loading @@ -21,11 +21,11 @@ import android.os.Handler; import android.os.UserHandle; import android.util.Log; import java.lang.ref.WeakReference; import androidx.annotation.Nullable; import androidx.annotation.RequiresPermission; import java.lang.ref.WeakReference; /** * LocalBluetoothManager provides a simplified interface on top of a subset of * the Bluetooth API. Note that {@link #getInstance} will return null Loading Loading @@ -111,10 +111,17 @@ public class LocalBluetoothManager { mContext = context.getApplicationContext(); mLocalAdapter = adapter; mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, this); mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext, handler, userHandle); mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalAdapter, mCachedDeviceManager, mEventManager); mEventManager = new BluetoothEventManager( mLocalAdapter, this, mCachedDeviceManager, mContext, handler, userHandle); mProfileManager = new LocalBluetoothProfileManager( mContext, mLocalAdapter, mCachedDeviceManager, mEventManager); mProfileManager.updateLocalProfiles(); mEventManager.readPairedDevices(); Loading packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java +12 −7 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static java.util.concurrent.TimeUnit.SECONDS; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; Loading @@ -37,13 +39,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.CountDownLatch; /** * Test that verifies that BluetoothEventManager can receive broadcasts for non-current * users for all bluetooth events. * Test that verifies that BluetoothEventManager can receive broadcasts for non-current users for * all bluetooth events. * * <p>Creation and deletion of users takes a long time, so marking this as a LargeTest. */ Loading @@ -64,9 +64,14 @@ public class BluetoothEventManagerIntegTest { mContext = InstrumentationRegistry.getTargetContext(); mUserManager = UserManager.get(mContext); mBluetoothEventManager = new BluetoothEventManager( mock(LocalBluetoothAdapter.class), mock(CachedBluetoothDeviceManager.class), mContext, /* handler= */ null, UserHandle.ALL); mBluetoothEventManager = new BluetoothEventManager( mock(LocalBluetoothAdapter.class), mock(LocalBluetoothManager.class), mock(CachedBluetoothDeviceManager.class), mContext, /* handler= */ null, UserHandle.ALL); // Create and start another user in the background. mOtherUser = mUserManager.createUser("TestUser", /* flags= */ 0); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java +190 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -29,35 +30,47 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.UserHandle; import android.platform.test.flag.junit.SetFlagsRule; import android.telephony.TelephonyManager; import com.android.settingslib.R; import com.android.settingslib.flags.Flags; import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.shadow.api.Shadow; import java.util.ArrayList; import java.util.Collections; import java.util.List; @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowBluetoothAdapter.class}) public class BluetoothEventManagerTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final String DEVICE_NAME = "test_device_name"; @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock private LocalBluetoothManager mBtManager; @Mock private CachedBluetoothDeviceManager mCachedDeviceManager; @Mock private BluetoothCallback mBluetoothCallback; Loading Loading @@ -96,8 +109,15 @@ public class BluetoothEventManagerTest { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mBluetoothEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null); mBluetoothEventManager = new BluetoothEventManager( mLocalAdapter, mBtManager, mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null); when(mBtManager.getProfileManager()).thenReturn(mLocalProfileManager); when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); when(mHfpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true); Loading @@ -113,8 +133,13 @@ public class BluetoothEventManagerTest { public void ifUserHandleIsNull_registerReceiverIsCalled() { Context mockContext = mock(Context.class); BluetoothEventManager eventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext, /* handler= */ null, /* userHandle= */ null); new BluetoothEventManager( mLocalAdapter, mBtManager, mCachedDeviceManager, mockContext, /* handler= */ null, /* userHandle= */ null); verify(mockContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED)); Loading @@ -124,8 +149,13 @@ public class BluetoothEventManagerTest { public void ifUserHandleSpecified_registerReceiverAsUserIsCalled() { Context mockContext = mock(Context.class); BluetoothEventManager eventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext, /* handler= */ null, UserHandle.ALL); new BluetoothEventManager( mLocalAdapter, mBtManager, mCachedDeviceManager, mockContext, /* handler= */ null, UserHandle.ALL); verify(mockContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq(UserHandle.ALL), any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED)); Loading Loading @@ -172,6 +202,160 @@ public class BluetoothEventManagerTest { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing flag is off. */ @Test public void dispatchProfileConnectionStateChanged_flagOff_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when the device does not * support audio sharing. */ @Test public void dispatchProfileConnectionStateChanged_notSupport_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing profile is * not ready. */ @Test public void dispatchProfileConnectionStateChanged_profileNotReady_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(false); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when triggered for profile * other than LE_AUDIO_BROADCAST_ASSISTANT or state other than STATE_DISCONNECTED. */ @Test public void dispatchProfileConnectionStateChanged_notAssistantProfile_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when assistant profile is * disconnected and audio sharing is enabled. */ @Test public void dispatchProfileConnectionStateChanged_audioSharing_updateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast).updateFallbackActiveDeviceIfNeeded(); } @Test public void dispatchAclConnectionStateChanged_aclDisconnected_shouldDispatchCallback() { mBluetoothEventManager.registerCallback(mBluetoothCallback); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java +14 −5 Original line number Diff line number Diff line Loading @@ -56,7 +56,8 @@ import java.util.List; @Config(shadows = {ShadowBluetoothAdapter.class}) public class LocalBluetoothProfileManagerTest { private final static long HISYNCID = 10; @Mock private LocalBluetoothManager mBtManager; @Mock private CachedBluetoothDeviceManager mDeviceManager; @Mock Loading @@ -77,13 +78,21 @@ public class LocalBluetoothProfileManagerTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); mLocalBluetoothAdapter = LocalBluetoothAdapter.getInstance(); mEventManager = spy(new BluetoothEventManager(mLocalBluetoothAdapter, mDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null)); mEventManager = spy( new BluetoothEventManager( mLocalBluetoothAdapter, mBtManager, mDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null)); mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice); when(mCachedBluetoothDevice.getDevice()).thenReturn(mDevice); mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter, mDeviceManager, mEventManager); mProfileManager = new LocalBluetoothProfileManager( mContext, mLocalBluetoothAdapter, mDeviceManager, mEventManager); } /** Loading Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +27 −6 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ public class BluetoothEventManager { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final LocalBluetoothAdapter mLocalAdapter; private final LocalBluetoothManager mBtManager; private final CachedBluetoothDeviceManager mDeviceManager; private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter; private final Map<String, Handler> mHandlerMap; Loading @@ -80,10 +81,15 @@ public class BluetoothEventManager { * userHandle passed in is {@code null}, we register event receiver for the * {@code context.getUser()} handle. */ BluetoothEventManager(LocalBluetoothAdapter adapter, CachedBluetoothDeviceManager deviceManager, Context context, android.os.Handler handler, @Nullable UserHandle userHandle) { BluetoothEventManager( LocalBluetoothAdapter adapter, LocalBluetoothManager btManager, CachedBluetoothDeviceManager deviceManager, Context context, android.os.Handler handler, @Nullable UserHandle userHandle) { mLocalAdapter = adapter; mBtManager = btManager; mDeviceManager = deviceManager; mAdapterIntentFilter = new IntentFilter(); mProfileIntentFilter = new IntentFilter(); Loading Loading @@ -210,11 +216,27 @@ public class BluetoothEventManager { } } void dispatchProfileConnectionStateChanged(@NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) { void dispatchProfileConnectionStateChanged( @NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) { for (BluetoothCallback callback : mCallbacks) { callback.onProfileConnectionStateChanged(device, state, bluetoothProfile); } // Trigger updateFallbackActiveDeviceIfNeeded when ASSISTANT profile disconnected when // audio sharing is enabled. if (bluetoothProfile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT && state == BluetoothAdapter.STATE_DISCONNECTED && BluetoothUtils.isAudioSharingEnabled()) { LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); if (profileManager != null && profileManager.getLeAudioBroadcastProfile() != null && profileManager.getLeAudioBroadcastProfile().isProfileReady() && profileManager.getLeAudioBroadcastAssistantProfile() != null && profileManager.getLeAudioBroadcastAssistantProfile().isProfileReady()) { Log.d(TAG, "updateFallbackActiveDeviceIfNeeded, ASSISTANT profile disconnected"); profileManager.getLeAudioBroadcastProfile().updateFallbackActiveDeviceIfNeeded(); } } } private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { Loading Loading @@ -536,7 +558,6 @@ public class BluetoothEventManager { default: Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action); return; } dispatchAclStateChanged(activeDevice, state); } Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java +13 −6 Original line number Diff line number Diff line Loading @@ -21,11 +21,11 @@ import android.os.Handler; import android.os.UserHandle; import android.util.Log; import java.lang.ref.WeakReference; import androidx.annotation.Nullable; import androidx.annotation.RequiresPermission; import java.lang.ref.WeakReference; /** * LocalBluetoothManager provides a simplified interface on top of a subset of * the Bluetooth API. Note that {@link #getInstance} will return null Loading Loading @@ -111,10 +111,17 @@ public class LocalBluetoothManager { mContext = context.getApplicationContext(); mLocalAdapter = adapter; mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, this); mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext, handler, userHandle); mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalAdapter, mCachedDeviceManager, mEventManager); mEventManager = new BluetoothEventManager( mLocalAdapter, this, mCachedDeviceManager, mContext, handler, userHandle); mProfileManager = new LocalBluetoothProfileManager( mContext, mLocalAdapter, mCachedDeviceManager, mEventManager); mProfileManager.updateLocalProfiles(); mEventManager.readPairedDevices(); Loading
packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java +12 −7 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static java.util.concurrent.TimeUnit.SECONDS; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; Loading @@ -37,13 +39,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.CountDownLatch; /** * Test that verifies that BluetoothEventManager can receive broadcasts for non-current * users for all bluetooth events. * Test that verifies that BluetoothEventManager can receive broadcasts for non-current users for * all bluetooth events. * * <p>Creation and deletion of users takes a long time, so marking this as a LargeTest. */ Loading @@ -64,9 +64,14 @@ public class BluetoothEventManagerIntegTest { mContext = InstrumentationRegistry.getTargetContext(); mUserManager = UserManager.get(mContext); mBluetoothEventManager = new BluetoothEventManager( mock(LocalBluetoothAdapter.class), mock(CachedBluetoothDeviceManager.class), mContext, /* handler= */ null, UserHandle.ALL); mBluetoothEventManager = new BluetoothEventManager( mock(LocalBluetoothAdapter.class), mock(LocalBluetoothManager.class), mock(CachedBluetoothDeviceManager.class), mContext, /* handler= */ null, UserHandle.ALL); // Create and start another user in the background. mOtherUser = mUserManager.createUser("TestUser", /* flags= */ 0); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java +190 −6 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -29,35 +30,47 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.UserHandle; import android.platform.test.flag.junit.SetFlagsRule; import android.telephony.TelephonyManager; import com.android.settingslib.R; import com.android.settingslib.flags.Flags; import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.shadow.api.Shadow; import java.util.ArrayList; import java.util.Collections; import java.util.List; @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowBluetoothAdapter.class}) public class BluetoothEventManagerTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final String DEVICE_NAME = "test_device_name"; @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock private LocalBluetoothManager mBtManager; @Mock private CachedBluetoothDeviceManager mCachedDeviceManager; @Mock private BluetoothCallback mBluetoothCallback; Loading Loading @@ -96,8 +109,15 @@ public class BluetoothEventManagerTest { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mBluetoothEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null); mBluetoothEventManager = new BluetoothEventManager( mLocalAdapter, mBtManager, mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null); when(mBtManager.getProfileManager()).thenReturn(mLocalProfileManager); when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); when(mHfpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true); Loading @@ -113,8 +133,13 @@ public class BluetoothEventManagerTest { public void ifUserHandleIsNull_registerReceiverIsCalled() { Context mockContext = mock(Context.class); BluetoothEventManager eventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext, /* handler= */ null, /* userHandle= */ null); new BluetoothEventManager( mLocalAdapter, mBtManager, mCachedDeviceManager, mockContext, /* handler= */ null, /* userHandle= */ null); verify(mockContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED)); Loading @@ -124,8 +149,13 @@ public class BluetoothEventManagerTest { public void ifUserHandleSpecified_registerReceiverAsUserIsCalled() { Context mockContext = mock(Context.class); BluetoothEventManager eventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext, /* handler= */ null, UserHandle.ALL); new BluetoothEventManager( mLocalAdapter, mBtManager, mCachedDeviceManager, mockContext, /* handler= */ null, UserHandle.ALL); verify(mockContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq(UserHandle.ALL), any(IntentFilter.class), eq(null), eq(null), eq(Context.RECEIVER_EXPORTED)); Loading Loading @@ -172,6 +202,160 @@ public class BluetoothEventManagerTest { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing flag is off. */ @Test public void dispatchProfileConnectionStateChanged_flagOff_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when the device does not * support audio sharing. */ @Test public void dispatchProfileConnectionStateChanged_notSupport_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when audio sharing profile is * not ready. */ @Test public void dispatchProfileConnectionStateChanged_profileNotReady_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(false); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should not call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when triggered for profile * other than LE_AUDIO_BROADCAST_ASSISTANT or state other than STATE_DISCONNECTED. */ @Test public void dispatchProfileConnectionStateChanged_notAssistantProfile_noUpdateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO); verify(broadcast, times(0)).updateFallbackActiveDeviceIfNeeded(); } /** * dispatchProfileConnectionStateChanged should call {@link * LocalBluetoothLeBroadcast}#updateFallbackActiveDeviceIfNeeded when assistant profile is * disconnected and audio sharing is enabled. */ @Test public void dispatchProfileConnectionStateChanged_audioSharing_updateFallbackDevice() { ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( BluetoothStatusCodes.FEATURE_SUPPORTED); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); LocalBluetoothLeBroadcast broadcast = mock(LocalBluetoothLeBroadcast.class); when(broadcast.isProfileReady()).thenReturn(true); LocalBluetoothLeBroadcastAssistant assistant = mock(LocalBluetoothLeBroadcastAssistant.class); when(assistant.isProfileReady()).thenReturn(true); LocalBluetoothProfileManager profileManager = mock(LocalBluetoothProfileManager.class); when(profileManager.getLeAudioBroadcastProfile()).thenReturn(broadcast); when(profileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(assistant); when(mBtManager.getProfileManager()).thenReturn(profileManager); mBluetoothEventManager.dispatchProfileConnectionStateChanged( mCachedBluetoothDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); verify(broadcast).updateFallbackActiveDeviceIfNeeded(); } @Test public void dispatchAclConnectionStateChanged_aclDisconnected_shouldDispatchCallback() { mBluetoothEventManager.registerCallback(mBluetoothCallback); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java +14 −5 Original line number Diff line number Diff line Loading @@ -56,7 +56,8 @@ import java.util.List; @Config(shadows = {ShadowBluetoothAdapter.class}) public class LocalBluetoothProfileManagerTest { private final static long HISYNCID = 10; @Mock private LocalBluetoothManager mBtManager; @Mock private CachedBluetoothDeviceManager mDeviceManager; @Mock Loading @@ -77,13 +78,21 @@ public class LocalBluetoothProfileManagerTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); mLocalBluetoothAdapter = LocalBluetoothAdapter.getInstance(); mEventManager = spy(new BluetoothEventManager(mLocalBluetoothAdapter, mDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null)); mEventManager = spy( new BluetoothEventManager( mLocalBluetoothAdapter, mBtManager, mDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null)); mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice); when(mCachedBluetoothDevice.getDevice()).thenReturn(mDevice); mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter, mDeviceManager, mEventManager); mProfileManager = new LocalBluetoothProfileManager( mContext, mLocalBluetoothAdapter, mDeviceManager, mEventManager); } /** Loading