Loading android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java +11 −14 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.bluetooth.IBluetoothA2dpSink; import android.content.AttributionSource; import android.content.Context; import android.media.AudioManager; import android.os.Looper; import android.sysprop.BluetoothProperties; import android.util.Log; Loading Loading @@ -54,6 +55,7 @@ public class A2dpSinkService extends ProfileService { new ConcurrentHashMap<>(1); private final A2dpSinkNativeInterface mNativeInterface; private final Looper mLooper; private final Object mActiveDeviceLock = new Object(); Loading @@ -74,12 +76,14 @@ public class A2dpSinkService extends ProfileService { A2dpSinkService() { mNativeInterface = requireNonNull(A2dpSinkNativeInterface.getInstance()); mLooper = Looper.getMainLooper(); } @VisibleForTesting A2dpSinkService(Context ctx, A2dpSinkNativeInterface nativeInterface) { A2dpSinkService(Context ctx, A2dpSinkNativeInterface nativeInterface, Looper looper) { attachBaseContext(ctx); mNativeInterface = requireNonNull(nativeInterface); mLooper = looper; onCreate(); } Loading Loading @@ -132,7 +136,6 @@ public class A2dpSinkService extends ProfileService { /** * Testing API to inject a mockA2dpSinkService. * @hide */ @VisibleForTesting public static synchronized void setA2dpSinkService(A2dpSinkService service) { Loading Loading @@ -437,12 +440,11 @@ public class A2dpSinkService extends ProfileService { /** * Remove a device's state machine. * * Called by the state machines when they disconnect. * <p>Called by the state machines when they disconnect. * * Visible for testing so it can be mocked and verified on. * <p>Visible for testing so it can be mocked and verified on. */ @VisibleForTesting public void removeStateMachine(A2dpSinkStateMachine stateMachine) { void removeStateMachine(A2dpSinkStateMachine stateMachine) { if (stateMachine == null) { return; } Loading @@ -456,7 +458,7 @@ public class A2dpSinkService extends ProfileService { protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) { A2dpSinkStateMachine newStateMachine = new A2dpSinkStateMachine(device, this, mNativeInterface); new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface); A2dpSinkStateMachine existingStateMachine = mDeviceStateMap.putIfAbsent(device, newStateMachine); // Given null is not a valid value in our map, ConcurrentHashMap will return null if the Loading @@ -465,11 +467,6 @@ public class A2dpSinkService extends ProfileService { if (existingStateMachine == null) { newStateMachine.start(); return newStateMachine; } else { // If you try to quit a StateMachine that hasn't been constructed yet, the StateMachine // spits out an NPE trying to read a state stack array that only gets made on start(). // We can just quit the thread made explicitly newStateMachine.getHandler().getLooper().quit(); } return existingStateMachine; } Loading Loading @@ -613,7 +610,7 @@ public class A2dpSinkService extends ProfileService { return; } A2dpSinkStateMachine stateMachine = getOrCreateStateMachine(device); stateMachine.sendMessage(A2dpSinkStateMachine.STACK_EVENT, event); stateMachine.onStackEvent(event); } private void onAudioStateChanged(StackEvent event) { Loading Loading @@ -641,6 +638,6 @@ public class A2dpSinkService extends ProfileService { return; } A2dpSinkStateMachine stateMachine = getStateMachineForDevice(device); stateMachine.sendMessage(A2dpSinkStateMachine.STACK_EVENT, event); stateMachine.onStackEvent(event); } } android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java +26 −21 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.media.AudioFormat; import android.os.Looper; import android.os.Message; import android.util.Log; Loading @@ -31,24 +32,24 @@ import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.State; import com.android.internal.util.StateMachine; public class A2dpSinkStateMachine extends StateMachine { static final String TAG = "A2dpSinkStateMachine"; class A2dpSinkStateMachine extends StateMachine { private static final String TAG = A2dpSinkStateMachine.class.getSimpleName(); static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); // 0->99 Events from Outside public static final int CONNECT = 1; public static final int DISCONNECT = 2; @VisibleForTesting static final int CONNECT = 1; @VisibleForTesting static final int DISCONNECT = 2; // 100->199 Internal Events protected static final int CLEANUP = 100; private static final int CONNECT_TIMEOUT = 101; @VisibleForTesting static final int CLEANUP = 100; @VisibleForTesting static final int CONNECT_TIMEOUT = 101; // 200->299 Events from Native static final int STACK_EVENT = 200; @VisibleForTesting static final int STACK_EVENT = 200; static final int CONNECT_TIMEOUT_MS = 10000; Loading @@ -64,9 +65,12 @@ public class A2dpSinkStateMachine extends StateMachine { protected int mMostRecentState = BluetoothProfile.STATE_DISCONNECTED; protected BluetoothAudioConfig mAudioConfig = null; A2dpSinkStateMachine(BluetoothDevice device, A2dpSinkService service, A2dpSinkStateMachine( Looper looper, BluetoothDevice device, A2dpSinkService service, A2dpSinkNativeInterface nativeInterface) { super(TAG); super(TAG, looper); mDevice = device; mDeviceAddress = Utils.getByteAddress(mDevice); mService = service; Loading Loading @@ -111,20 +115,21 @@ public class A2dpSinkStateMachine extends StateMachine { return mDevice; } /** * send the Connect command asynchronously */ public final void connect() { /** send the Connect command asynchronously */ final void connect() { sendMessage(CONNECT); } /** * send the Disconnect command asynchronously */ public final void disconnect() { /** send the Disconnect command asynchronously */ final void disconnect() { sendMessage(DISCONNECT); } /** send the stack event asynchronously */ final void onStackEvent(StackEvent event) { sendMessage(STACK_EVENT, event); } /** * Dump the current State Machine to the string builder. * @param sb output string Loading android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java +68 −57 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.media.AudioFormat; import android.os.test.TestLooper; import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; Loading Loading @@ -67,6 +68,8 @@ public class A2dpSinkServiceTest { private BluetoothDevice mDevice5; private BluetoothDevice mDevice6; private TestLooper mLooper; private static final int TEST_SAMPLE_RATE = 44; private static final int TEST_CHANNEL_COUNT = 1; Loading @@ -75,74 +78,65 @@ public class A2dpSinkServiceTest { mTargetContext = InstrumentationRegistry.getTargetContext(); MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); mAdapter = BluetoothAdapter.getDefaultAdapter(); assertThat(mAdapter).isNotNull(); mDevice1 = makeBluetoothDevice("11:11:11:11:11:11"); mDevice2 = makeBluetoothDevice("22:22:22:22:22:22"); mDevice3 = makeBluetoothDevice("33:33:33:33:33:33"); mDevice4 = makeBluetoothDevice("44:44:44:44:44:44"); mDevice5 = makeBluetoothDevice("55:55:55:55:55:55"); mDevice6 = makeBluetoothDevice("66:66:66:66:66:66"); mDevice1 = mAdapter.getRemoteDevice("11:11:11:11:11:11"); mDevice2 = mAdapter.getRemoteDevice("22:22:22:22:22:22"); mDevice3 = mAdapter.getRemoteDevice("33:33:33:33:33:33"); mDevice4 = mAdapter.getRemoteDevice("44:44:44:44:44:44"); mDevice5 = mAdapter.getRemoteDevice("55:55:55:55:55:55"); mDevice6 = mAdapter.getRemoteDevice("66:66:66:66:66:66"); BluetoothDevice[] bondedDevices = new BluetoothDevice[]{ mDevice1, mDevice2, mDevice3, mDevice4, mDevice5, mDevice6 }; // Setup the adapter service and start our service under test TestUtils.setAdapterService(mAdapterService); doReturn(true).when(mDatabaseManager).setProfileConnectionPolicy(any(), anyInt(), anyInt()); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); doReturn(bondedDevices).when(mAdapterService).getBondedDevices(); when(mDatabaseManager.setProfileConnectionPolicy(any(), anyInt(), anyInt())).thenReturn(true); setMaxConnectedAudioDevices(1); A2dpSinkNativeInterface.setInstance(mNativeInterface); TestUtils.startService(mServiceRule, A2dpSinkService.class); mService = A2dpSinkService.getA2dpSinkService(); assertThat(mService).isNotNull(); doReturn(1).when(mAdapterService).getMaxConnectedAudioDevices(); TestUtils.setAdapterService(mAdapterService); doReturn(true).when(mNativeInterface).setActiveDevice(any()); mService = new A2dpSinkService(mTargetContext, mNativeInterface, mLooper.getLooper()); mService.doStart(); assertThat(mLooper.nextMessage()).isNull(); } @After public void tearDown() throws Exception { TestUtils.stopService(mServiceRule, A2dpSinkService.class); A2dpSinkNativeInterface.setInstance(null); mService = A2dpSinkService.getA2dpSinkService(); assertThat(mService).isNull(); assertThat(mLooper.nextMessage()).isNull(); mService.doStop(); assertThat(A2dpSinkService.getA2dpSinkService()).isNull(); TestUtils.clearAdapterService(mAdapterService); } private void syncHandler(int... what) { TestUtils.syncHandler(mLooper, what); } private void setupDeviceConnection(BluetoothDevice device) { assertThat(mLooper.nextMessage()).isNull(); assertThat(mService.getConnectionState(device)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); assertThat(mLooper.nextMessage()).isNull(); assertThat(mService.connect(device)).isTrue(); sendConnectionEvent(device, StackEvent.CONNECTION_STATE_CONNECTED); waitForDeviceProcessing(device); syncHandler(-2 /* SM_INIT_CMD */, A2dpSinkStateMachine.CONNECT); StackEvent nativeEvent = StackEvent.connectionStateChanged(device, StackEvent.CONNECTION_STATE_CONNECTED); mService.messageFromNative(nativeEvent); syncHandler(A2dpSinkStateMachine.STACK_EVENT); assertThat(mService.getConnectionState(device)).isEqualTo( BluetoothProfile.STATE_CONNECTED); } private void sendConnectionEvent(BluetoothDevice device, int newState) { StackEvent event = StackEvent.connectionStateChanged(device, newState); mService.messageFromNative(event); } private void waitForDeviceProcessing(BluetoothDevice device) { A2dpSinkStateMachine sm = mService.getStateMachineForDevice(device); if (sm == null) return; TestUtils.waitForLooperToFinishScheduledTask(sm.getHandler().getLooper()); } private BluetoothDevice makeBluetoothDevice(String address) { return mAdapter.getRemoteDevice(address); } /** * Set the upper connected device limit */ private void setMaxConnectedAudioDevices(int maxConnectedAudioDevices) { when(mAdapterService.getMaxConnectedAudioDevices()).thenReturn(maxConnectedAudioDevices); } /** * Mock the priority of a bluetooth device * Loading @@ -159,7 +153,7 @@ public class A2dpSinkServiceTest { */ @Test public void testInitialize() { assertThat(A2dpSinkService.getA2dpSinkService()).isNotNull(); assertThat(A2dpSinkService.getA2dpSinkService()).isEqualTo(mService); } /** Loading Loading @@ -204,7 +198,7 @@ public class A2dpSinkServiceTest { */ @Test public void testConnectMultipleDevices() { setMaxConnectedAudioDevices(5); doReturn(5).when(mAdapterService).getMaxConnectedAudioDevices(); mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); mockDevicePriority(mDevice2, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -229,9 +223,11 @@ public class A2dpSinkServiceTest { setupDeviceConnection(mDevice1); assertThat(mService.disconnect(mDevice1)).isTrue(); waitForDeviceProcessing(mDevice1); syncHandler(A2dpSinkStateMachine.DISCONNECT); assertThat(mService.getConnectionState(mDevice1)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */); } /** Loading Loading @@ -292,7 +288,7 @@ public class A2dpSinkServiceTest { StackEvent audioConfigChanged = StackEvent.audioConfigChanged(mDevice1, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT); mService.messageFromNative(audioConfigChanged); waitForDeviceProcessing(mDevice1); syncHandler(A2dpSinkStateMachine.STACK_EVENT); BluetoothAudioConfig expected = new BluetoothAudioConfig(TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT, AudioFormat.ENCODING_PCM_16BIT); Loading Loading @@ -406,8 +402,11 @@ public class A2dpSinkServiceTest { public void testSetConnectionPolicyDeviceAllowed() { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_ALLOWED); } /** Loading @@ -417,8 +416,11 @@ public class A2dpSinkServiceTest { public void testSetConnectionPolicyDeviceForbiddenWhileNotConnected() { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); } /** Loading @@ -432,12 +434,18 @@ public class A2dpSinkServiceTest { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); waitForDeviceProcessing(mDevice1); syncHandler(A2dpSinkStateMachine.DISCONNECT); verify(mNativeInterface).disconnectA2dpSink(eq(mDevice1)); assertThat(mService.getConnectionState(mDevice1)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */); } /** Loading @@ -447,8 +455,11 @@ public class A2dpSinkServiceTest { public void testSetConnectionPolicyDeviceUnknown() { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); } /** Loading android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java +80 −77 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java +11 −14 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.bluetooth.IBluetoothA2dpSink; import android.content.AttributionSource; import android.content.Context; import android.media.AudioManager; import android.os.Looper; import android.sysprop.BluetoothProperties; import android.util.Log; Loading Loading @@ -54,6 +55,7 @@ public class A2dpSinkService extends ProfileService { new ConcurrentHashMap<>(1); private final A2dpSinkNativeInterface mNativeInterface; private final Looper mLooper; private final Object mActiveDeviceLock = new Object(); Loading @@ -74,12 +76,14 @@ public class A2dpSinkService extends ProfileService { A2dpSinkService() { mNativeInterface = requireNonNull(A2dpSinkNativeInterface.getInstance()); mLooper = Looper.getMainLooper(); } @VisibleForTesting A2dpSinkService(Context ctx, A2dpSinkNativeInterface nativeInterface) { A2dpSinkService(Context ctx, A2dpSinkNativeInterface nativeInterface, Looper looper) { attachBaseContext(ctx); mNativeInterface = requireNonNull(nativeInterface); mLooper = looper; onCreate(); } Loading Loading @@ -132,7 +136,6 @@ public class A2dpSinkService extends ProfileService { /** * Testing API to inject a mockA2dpSinkService. * @hide */ @VisibleForTesting public static synchronized void setA2dpSinkService(A2dpSinkService service) { Loading Loading @@ -437,12 +440,11 @@ public class A2dpSinkService extends ProfileService { /** * Remove a device's state machine. * * Called by the state machines when they disconnect. * <p>Called by the state machines when they disconnect. * * Visible for testing so it can be mocked and verified on. * <p>Visible for testing so it can be mocked and verified on. */ @VisibleForTesting public void removeStateMachine(A2dpSinkStateMachine stateMachine) { void removeStateMachine(A2dpSinkStateMachine stateMachine) { if (stateMachine == null) { return; } Loading @@ -456,7 +458,7 @@ public class A2dpSinkService extends ProfileService { protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) { A2dpSinkStateMachine newStateMachine = new A2dpSinkStateMachine(device, this, mNativeInterface); new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface); A2dpSinkStateMachine existingStateMachine = mDeviceStateMap.putIfAbsent(device, newStateMachine); // Given null is not a valid value in our map, ConcurrentHashMap will return null if the Loading @@ -465,11 +467,6 @@ public class A2dpSinkService extends ProfileService { if (existingStateMachine == null) { newStateMachine.start(); return newStateMachine; } else { // If you try to quit a StateMachine that hasn't been constructed yet, the StateMachine // spits out an NPE trying to read a state stack array that only gets made on start(). // We can just quit the thread made explicitly newStateMachine.getHandler().getLooper().quit(); } return existingStateMachine; } Loading Loading @@ -613,7 +610,7 @@ public class A2dpSinkService extends ProfileService { return; } A2dpSinkStateMachine stateMachine = getOrCreateStateMachine(device); stateMachine.sendMessage(A2dpSinkStateMachine.STACK_EVENT, event); stateMachine.onStackEvent(event); } private void onAudioStateChanged(StackEvent event) { Loading Loading @@ -641,6 +638,6 @@ public class A2dpSinkService extends ProfileService { return; } A2dpSinkStateMachine stateMachine = getStateMachineForDevice(device); stateMachine.sendMessage(A2dpSinkStateMachine.STACK_EVENT, event); stateMachine.onStackEvent(event); } }
android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java +26 −21 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.media.AudioFormat; import android.os.Looper; import android.os.Message; import android.util.Log; Loading @@ -31,24 +32,24 @@ import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.State; import com.android.internal.util.StateMachine; public class A2dpSinkStateMachine extends StateMachine { static final String TAG = "A2dpSinkStateMachine"; class A2dpSinkStateMachine extends StateMachine { private static final String TAG = A2dpSinkStateMachine.class.getSimpleName(); static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); // 0->99 Events from Outside public static final int CONNECT = 1; public static final int DISCONNECT = 2; @VisibleForTesting static final int CONNECT = 1; @VisibleForTesting static final int DISCONNECT = 2; // 100->199 Internal Events protected static final int CLEANUP = 100; private static final int CONNECT_TIMEOUT = 101; @VisibleForTesting static final int CLEANUP = 100; @VisibleForTesting static final int CONNECT_TIMEOUT = 101; // 200->299 Events from Native static final int STACK_EVENT = 200; @VisibleForTesting static final int STACK_EVENT = 200; static final int CONNECT_TIMEOUT_MS = 10000; Loading @@ -64,9 +65,12 @@ public class A2dpSinkStateMachine extends StateMachine { protected int mMostRecentState = BluetoothProfile.STATE_DISCONNECTED; protected BluetoothAudioConfig mAudioConfig = null; A2dpSinkStateMachine(BluetoothDevice device, A2dpSinkService service, A2dpSinkStateMachine( Looper looper, BluetoothDevice device, A2dpSinkService service, A2dpSinkNativeInterface nativeInterface) { super(TAG); super(TAG, looper); mDevice = device; mDeviceAddress = Utils.getByteAddress(mDevice); mService = service; Loading Loading @@ -111,20 +115,21 @@ public class A2dpSinkStateMachine extends StateMachine { return mDevice; } /** * send the Connect command asynchronously */ public final void connect() { /** send the Connect command asynchronously */ final void connect() { sendMessage(CONNECT); } /** * send the Disconnect command asynchronously */ public final void disconnect() { /** send the Disconnect command asynchronously */ final void disconnect() { sendMessage(DISCONNECT); } /** send the stack event asynchronously */ final void onStackEvent(StackEvent event) { sendMessage(STACK_EVENT, event); } /** * Dump the current State Machine to the string builder. * @param sb output string Loading
android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java +68 −57 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.media.AudioFormat; import android.os.test.TestLooper; import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; Loading Loading @@ -67,6 +68,8 @@ public class A2dpSinkServiceTest { private BluetoothDevice mDevice5; private BluetoothDevice mDevice6; private TestLooper mLooper; private static final int TEST_SAMPLE_RATE = 44; private static final int TEST_CHANNEL_COUNT = 1; Loading @@ -75,74 +78,65 @@ public class A2dpSinkServiceTest { mTargetContext = InstrumentationRegistry.getTargetContext(); MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); mAdapter = BluetoothAdapter.getDefaultAdapter(); assertThat(mAdapter).isNotNull(); mDevice1 = makeBluetoothDevice("11:11:11:11:11:11"); mDevice2 = makeBluetoothDevice("22:22:22:22:22:22"); mDevice3 = makeBluetoothDevice("33:33:33:33:33:33"); mDevice4 = makeBluetoothDevice("44:44:44:44:44:44"); mDevice5 = makeBluetoothDevice("55:55:55:55:55:55"); mDevice6 = makeBluetoothDevice("66:66:66:66:66:66"); mDevice1 = mAdapter.getRemoteDevice("11:11:11:11:11:11"); mDevice2 = mAdapter.getRemoteDevice("22:22:22:22:22:22"); mDevice3 = mAdapter.getRemoteDevice("33:33:33:33:33:33"); mDevice4 = mAdapter.getRemoteDevice("44:44:44:44:44:44"); mDevice5 = mAdapter.getRemoteDevice("55:55:55:55:55:55"); mDevice6 = mAdapter.getRemoteDevice("66:66:66:66:66:66"); BluetoothDevice[] bondedDevices = new BluetoothDevice[]{ mDevice1, mDevice2, mDevice3, mDevice4, mDevice5, mDevice6 }; // Setup the adapter service and start our service under test TestUtils.setAdapterService(mAdapterService); doReturn(true).when(mDatabaseManager).setProfileConnectionPolicy(any(), anyInt(), anyInt()); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); doReturn(bondedDevices).when(mAdapterService).getBondedDevices(); when(mDatabaseManager.setProfileConnectionPolicy(any(), anyInt(), anyInt())).thenReturn(true); setMaxConnectedAudioDevices(1); A2dpSinkNativeInterface.setInstance(mNativeInterface); TestUtils.startService(mServiceRule, A2dpSinkService.class); mService = A2dpSinkService.getA2dpSinkService(); assertThat(mService).isNotNull(); doReturn(1).when(mAdapterService).getMaxConnectedAudioDevices(); TestUtils.setAdapterService(mAdapterService); doReturn(true).when(mNativeInterface).setActiveDevice(any()); mService = new A2dpSinkService(mTargetContext, mNativeInterface, mLooper.getLooper()); mService.doStart(); assertThat(mLooper.nextMessage()).isNull(); } @After public void tearDown() throws Exception { TestUtils.stopService(mServiceRule, A2dpSinkService.class); A2dpSinkNativeInterface.setInstance(null); mService = A2dpSinkService.getA2dpSinkService(); assertThat(mService).isNull(); assertThat(mLooper.nextMessage()).isNull(); mService.doStop(); assertThat(A2dpSinkService.getA2dpSinkService()).isNull(); TestUtils.clearAdapterService(mAdapterService); } private void syncHandler(int... what) { TestUtils.syncHandler(mLooper, what); } private void setupDeviceConnection(BluetoothDevice device) { assertThat(mLooper.nextMessage()).isNull(); assertThat(mService.getConnectionState(device)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); assertThat(mLooper.nextMessage()).isNull(); assertThat(mService.connect(device)).isTrue(); sendConnectionEvent(device, StackEvent.CONNECTION_STATE_CONNECTED); waitForDeviceProcessing(device); syncHandler(-2 /* SM_INIT_CMD */, A2dpSinkStateMachine.CONNECT); StackEvent nativeEvent = StackEvent.connectionStateChanged(device, StackEvent.CONNECTION_STATE_CONNECTED); mService.messageFromNative(nativeEvent); syncHandler(A2dpSinkStateMachine.STACK_EVENT); assertThat(mService.getConnectionState(device)).isEqualTo( BluetoothProfile.STATE_CONNECTED); } private void sendConnectionEvent(BluetoothDevice device, int newState) { StackEvent event = StackEvent.connectionStateChanged(device, newState); mService.messageFromNative(event); } private void waitForDeviceProcessing(BluetoothDevice device) { A2dpSinkStateMachine sm = mService.getStateMachineForDevice(device); if (sm == null) return; TestUtils.waitForLooperToFinishScheduledTask(sm.getHandler().getLooper()); } private BluetoothDevice makeBluetoothDevice(String address) { return mAdapter.getRemoteDevice(address); } /** * Set the upper connected device limit */ private void setMaxConnectedAudioDevices(int maxConnectedAudioDevices) { when(mAdapterService.getMaxConnectedAudioDevices()).thenReturn(maxConnectedAudioDevices); } /** * Mock the priority of a bluetooth device * Loading @@ -159,7 +153,7 @@ public class A2dpSinkServiceTest { */ @Test public void testInitialize() { assertThat(A2dpSinkService.getA2dpSinkService()).isNotNull(); assertThat(A2dpSinkService.getA2dpSinkService()).isEqualTo(mService); } /** Loading Loading @@ -204,7 +198,7 @@ public class A2dpSinkServiceTest { */ @Test public void testConnectMultipleDevices() { setMaxConnectedAudioDevices(5); doReturn(5).when(mAdapterService).getMaxConnectedAudioDevices(); mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED); mockDevicePriority(mDevice2, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -229,9 +223,11 @@ public class A2dpSinkServiceTest { setupDeviceConnection(mDevice1); assertThat(mService.disconnect(mDevice1)).isTrue(); waitForDeviceProcessing(mDevice1); syncHandler(A2dpSinkStateMachine.DISCONNECT); assertThat(mService.getConnectionState(mDevice1)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */); } /** Loading Loading @@ -292,7 +288,7 @@ public class A2dpSinkServiceTest { StackEvent audioConfigChanged = StackEvent.audioConfigChanged(mDevice1, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT); mService.messageFromNative(audioConfigChanged); waitForDeviceProcessing(mDevice1); syncHandler(A2dpSinkStateMachine.STACK_EVENT); BluetoothAudioConfig expected = new BluetoothAudioConfig(TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT, AudioFormat.ENCODING_PCM_16BIT); Loading Loading @@ -406,8 +402,11 @@ public class A2dpSinkServiceTest { public void testSetConnectionPolicyDeviceAllowed() { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_ALLOWED); } /** Loading @@ -417,8 +416,11 @@ public class A2dpSinkServiceTest { public void testSetConnectionPolicyDeviceForbiddenWhileNotConnected() { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); } /** Loading @@ -432,12 +434,18 @@ public class A2dpSinkServiceTest { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); waitForDeviceProcessing(mDevice1); syncHandler(A2dpSinkStateMachine.DISCONNECT); verify(mNativeInterface).disconnectA2dpSink(eq(mDevice1)); assertThat(mService.getConnectionState(mDevice1)).isEqualTo( BluetoothProfile.STATE_DISCONNECTED); syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */); } /** Loading @@ -447,8 +455,11 @@ public class A2dpSinkServiceTest { public void testSetConnectionPolicyDeviceUnknown() { assertThat(mService.setConnectionPolicy(mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN)).isTrue(); verify(mDatabaseManager, times(1)).setProfileConnectionPolicy(mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); verify(mDatabaseManager) .setProfileConnectionPolicy( mDevice1, BluetoothProfile.A2DP_SINK, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); } /** Loading
android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java +80 −77 File changed.Preview size limit exceeded, changes collapsed. Show changes