Loading android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java +14 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.support.v4.media.MediaBrowserCompat.MediaItem; import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.flags.Flags; import com.google.common.annotations.VisibleForTesting; Loading Loading @@ -80,10 +81,22 @@ public class BrowseTree { mRootNode = new BrowseNode(new AvrcpItem.Builder() .setUuid(ROOT).setTitle(ROOT).setBrowsable(true).build()); mRootNode.setCached(true); } else { } else if (!Flags.randomizeDeviceLevelMediaIds()) { mRootNode = new BrowseNode(new AvrcpItem.Builder().setDevice(device) .setUuid(ROOT + device.getAddress().toString()) .setTitle(Utils.getName(device)).setBrowsable(true).build()); } else { mRootNode = new BrowseNode( new AvrcpItem.Builder() .setDevice(device) .setUuid( ROOT + device.getAddress().toString() + UUID.randomUUID().toString()) .setTitle(Utils.getName(device)) .setBrowsable(true) .build()); } mRootNode.mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST; Loading android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java +58 −3 Original line number Diff line number Diff line Loading @@ -30,7 +30,9 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.media.AudioManager; import android.platform.test.flag.junit.SetFlagsRule; import android.support.v4.media.session.PlaybackStateCompat; import androidx.test.InstrumentationRegistry; Loading @@ -38,9 +40,12 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService.BrowseResult; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; import org.junit.After; import org.junit.Before; Loading @@ -61,6 +66,11 @@ import java.util.List; public class AvrcpControllerServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; private static final byte[] REMOTE_DEVICE_ADDRESS_AS_ARRAY = new byte[]{0, 0, 0, 0, 0, 0}; private static final String REMOTE_DEVICE_ADDRESS_2 = "11:11:11:11:11:11"; private static final byte[] REMOTE_DEVICE_ADDRESS_AS_ARRAY_2 = new byte[] {11, 11, 11, 11, 11, 11}; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private AvrcpControllerService mService = null; private BluetoothAdapter mAdapter = null; Loading @@ -70,11 +80,18 @@ public class AvrcpControllerServiceTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private A2dpSinkService mA2dpSinkService; @Mock private AdapterService mAdapterService; @Mock private AvrcpControllerStateMachine mStateMachine; @Mock private AvrcpControllerStateMachine mStateMachine2; @Mock private AvrcpControllerNativeInterface mNativeInterface; @Mock private Resources mMockResources; private BluetoothDevice mRemoteDevice; private BluetoothDevice mRemoteDevice2; @Mock private AvrcpControllerStateMachine mAvrcpStateMachine; @Before public void setUp() throws Exception { Loading @@ -86,17 +103,29 @@ public class AvrcpControllerServiceTest { // Try getting the Bluetooth adapter mAdapter = BluetoothAdapter.getDefaultAdapter(); assertThat(mAdapter).isNotNull(); // Set a mock A2dpSinkService for audio focus calls A2dpSinkService.setA2dpSinkService(mA2dpSinkService); when(mMockResources.getBoolean(R.bool.a2dp_sink_automatically_request_audio_focus)) .thenReturn(true); mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); mService.mDeviceStateMap.put(mRemoteDevice, mStateMachine); final Intent bluetoothBrowserMediaServiceStartIntent = TestUtils.prepareIntentToStartBluetoothBrowserMediaService(); mBluetoothBrowserMediaServiceTestRule.startService(bluetoothBrowserMediaServiceStartIntent); // Set up device and state machine under test mRemoteDevice2 = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS_2); mService.mDeviceStateMap.put(mRemoteDevice2, mStateMachine2); when(mA2dpSinkService.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true); } @After public void tearDown() throws Exception { mService.stop(); AvrcpControllerNativeInterface.setInstance(null); A2dpSinkService.setA2dpSinkService(null); mService = AvrcpControllerService.getAvrcpControllerService(); assertThat(mService).isNull(); TestUtils.clearAdapterService(mAdapterService); Loading Loading @@ -142,6 +171,7 @@ public class AvrcpControllerServiceTest { @Test public void setActiveDevice_whenA2dpSinkServiceIsNotInitailized_returnsFalse() { A2dpSinkService.setA2dpSinkService(null); assertThat(mService.setActiveDevice(mRemoteDevice)).isFalse(); assertThat(mService.getActiveDevice()).isNull(); Loading Loading @@ -465,7 +495,8 @@ public class AvrcpControllerServiceTest { mService.handleGetPlayerItemsRsp(mRemoteDevice, items); verify(mStateMachine).sendMessage( verify(mStateMachine) .sendMessage( eq(AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_PLAYER_ITEMS), eq(items)); } Loading @@ -487,4 +518,28 @@ public class AvrcpControllerServiceTest { mService.onAudioFocusStateChanged(AudioManager.AUDIOFOCUS_LOSS); assertThat(BluetoothMediaBrowserService.isActive()).isFalse(); } /** * Connect first device and check that it is the active device. Pair a second device, then * disconnect and repair this known second device. Confirm that audio focus is maintained by * first device by checking that it has remained as the active device. */ @Test public void testActiveDeviceMaintainsAudioFocusWhenOtherDeviceConnects_audioFocusMaintained() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); mService.onConnectionStateChanged(true, true, mRemoteDevice); // check set active device is called verify(mA2dpSinkService).setActiveDevice(mRemoteDevice); when(mA2dpSinkService.getActiveDevice()).thenReturn(mRemoteDevice); // connect another phone mService.onConnectionStateChanged(true, true, mRemoteDevice2); verify(mA2dpSinkService, times(0)).setActiveDevice(mRemoteDevice2); // disconnect and reconnect other phone mService.onConnectionStateChanged(false, false, mRemoteDevice2); mService.onConnectionStateChanged(true, true, mRemoteDevice2); verify(mA2dpSinkService, times(0)).setActiveDevice(mRemoteDevice2); } } android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +46 −34 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.bluetooth.avrcpcontroller; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; Loading @@ -29,6 +31,7 @@ import android.content.res.Resources; import android.media.AudioManager; import android.os.Bundle; import android.os.Looper; import android.platform.test.flag.junit.SetFlagsRule; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; Loading @@ -44,6 +47,7 @@ import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; import org.hamcrest.core.IsInstanceOf; import org.junit.After; Loading @@ -68,6 +72,10 @@ public class AvrcpControllerStateMachineTest { private static final int CONNECT_TIMEOUT_TEST_MILLIS = 1000; private static final int KEY_DOWN = 0; private static final int KEY_UP = 1; private static final int UUID_START = 0; private static final int UUID_LENGTH = 25; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private BluetoothAdapter mAdapter; Loading Loading @@ -135,6 +143,7 @@ public class AvrcpControllerStateMachineTest { // Set up device and state machine under test mTestDevice = mAdapter.getRemoteDevice(mTestAddress); mAvrcpStateMachine = makeStateMachine(mTestDevice); setActiveDevice(mTestDevice); } Loading Loading @@ -461,6 +470,27 @@ public class AvrcpControllerStateMachineTest { verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine)); } /** Get the root of the device */ @Test public void testGetDeviceRootNode_flagRandomDeviceIdDisabled_rootNodeMatchesUuidFormat() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); } /** Get the root of the device */ @Test public void testGetDeviceRootNode_flagRandomDeviceIdEnabled_rootNodeMatchesUuidFormat() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; assertThat((results.getID()).substring(UUID_START, UUID_LENGTH)).isEqualTo(rootName); } /** * Test to make sure the state machine is tracking the correct device */ Loading Loading @@ -716,12 +746,8 @@ public class AvrcpControllerStateMachineTest { @FlakyTest public void testBrowsingCommands() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); final String playerName = "Player 1"; //Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID()); Loading Loading @@ -764,14 +790,13 @@ public class AvrcpControllerStateMachineTest { @Test public void testAvailablePlayersChanged() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Send an available players have changed event mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED); // Verify we've uncached our browse root and made the call to fetch new players Assert.assertFalse(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertFalse(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getPlayerList(eq(mTestAddress), eq(0), eq(19)); } Loading @@ -783,7 +808,6 @@ public class AvrcpControllerStateMachineTest { @Test public void testAvailablePlayersReceived_AddressedPlayerExists() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Set an addressed player that will be in the available players set. A new player triggers // a now playing list download, so send back nothing. Loading @@ -801,7 +825,7 @@ public class AvrcpControllerStateMachineTest { AvrcpControllerStateMachine.MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED); // Verify we've uncached our browse root and made the call to fetch new players Assert.assertFalse(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertFalse(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getPlayerList(eq(mTestAddress), eq(0), eq(19)); Loading @@ -821,7 +845,7 @@ public class AvrcpControllerStateMachineTest { // Verify we processed the first players properly. Note the addressed player should always // be in the available player set. Assert.assertTrue(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertTrue(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); Assert.assertTrue(players.contains(mAvrcpStateMachine.getAddressedPlayerId())); Assert.assertEquals(testPlayers.size(), players.size()); Loading @@ -846,14 +870,13 @@ public class AvrcpControllerStateMachineTest { @Test public void testAvailablePlayersReceived_AddressedPlayerDoesNotExist() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Send an available players have changed event mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED); // Verify we've uncached our browse root and made the call to fetch new players Assert.assertFalse(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertFalse(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getPlayerList(eq(mTestAddress), eq(0), eq(19)); Loading @@ -874,7 +897,7 @@ public class AvrcpControllerStateMachineTest { // Verify we processed the players properly. Note the addressed player is currently the // default player and is not in the available player set sent. This means we'll have an // extra player at ID -1. Assert.assertTrue(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertTrue(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); Assert.assertTrue(players.contains(mAvrcpStateMachine.getAddressedPlayerId())); Assert.assertEquals(testPlayers.size() + 1, players.size()); Loading @@ -899,11 +922,8 @@ public class AvrcpControllerStateMachineTest { @Test public void testAddressedPlayerChangedToNewKnownPlayer() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID()); Loading Loading @@ -962,11 +982,9 @@ public class AvrcpControllerStateMachineTest { @Test public void testAddressedPlayerChangedToUnknownPlayer() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, rootNode.getID()); BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(rootNode.getID()); Loading Loading @@ -1009,7 +1027,6 @@ public class AvrcpControllerStateMachineTest { @Test public void testAddressedPlayerChangedToSamePlayerId() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Set the addressed player so we can change to the same one mAvrcpStateMachine.sendMessage( Loading @@ -1022,8 +1039,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Get the root of the device BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, rootNode.getID()); BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(rootNode.getID()); Loading Loading @@ -1080,12 +1096,10 @@ public class AvrcpControllerStateMachineTest { @Test public void testPlayWhileBrowsing() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); final String playerName = "Player 1"; // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID()); Loading Loading @@ -2083,12 +2097,11 @@ public class AvrcpControllerStateMachineTest { */ @Test public void testBrowseRequestWhileDisconnected_requestDropped() { final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); setUpConnectedState(true, false); sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_GAIN); clearInvocations(mAvrcpControllerService); clearInvocations(mNativeInterface); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.findNode(rootName); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.mBrowseTree.mRootNode; mAvrcpStateMachine.requestContents(deviceRoot); TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); verifyNoMoreInteractions(mAvrcpControllerService); Loading @@ -2101,12 +2114,11 @@ public class AvrcpControllerStateMachineTest { */ @Test public void testBrowseRequestWhileDisconnectedThenRequestWhileConnected_secondRequestSent() { final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); setUpConnectedState(true, false); sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_GAIN); clearInvocations(mAvrcpControllerService); clearInvocations(mNativeInterface); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.findNode(rootName); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.mBrowseTree.mRootNode; mAvrcpStateMachine.requestContents(deviceRoot); // issues a player list fetch mAvrcpStateMachine.connect(StackEvent.connectionStateChanged(true, true)); Loading android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java +33 −0 Original line number Diff line number Diff line Loading @@ -20,10 +20,13 @@ import static com.google.common.truth.Truth.assertThat; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.platform.test.flag.junit.SetFlagsRule; import com.android.bluetooth.avrcpcontroller.BrowseTree.BrowseNode; import com.android.bluetooth.flags.Flags; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import java.util.Set; Loading @@ -33,6 +36,8 @@ public class BrowseTreeTest { private static final String TEST_HANDLE = "test_handle"; private static final String TEST_NODE_ID = "test_node_id"; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private final byte[] mTestAddress = new byte[]{01, 01, 01, 01, 01, 01}; private BluetoothAdapter mAdapter; private BluetoothDevice mTestDevice = null; Loading Loading @@ -89,6 +94,18 @@ public class BrowseTreeTest { assertThat(browseTree.mRootNode.getChildrenCount()).isEqualTo(1); } @Test public void sameDeviceDifferentBrowseTrees_uniqueMediaIds() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); BrowseTree browseTree1 = new BrowseTree(mTestDevice); BrowseTree browseTree2 = new BrowseTree(mTestDevice); String mediaId1 = browseTree1.mRootNode.getID(); String mediaId2 = browseTree2.mRootNode.getID(); assertThat(mediaId1).isNotEqualTo(mediaId2); } @Test public void findBrowseNodeByIDForRoot() { BrowseTree browseTree = new BrowseTree(null); Loading @@ -102,6 +119,14 @@ public class BrowseTreeTest { assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); } @Test public void findBrowseNodeByIDForDevice_flagEnabled() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); BrowseTree browseTree = new BrowseTree(mTestDevice); final String deviceId = browseTree.mRootNode.getID(); assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); } @Test public void findBrowseNodeByIDForIllegalId() { BrowseTree browseTree = new BrowseTree(mTestDevice); Loading @@ -117,6 +142,14 @@ public class BrowseTreeTest { assertThat(browseTree.getCurrentBrowsedFolder()).isEqualTo(browseTree.mNowPlayingNode); } @Test public void findBrowseNodeByIDForDevice_withRandomDeviceID_nodeIsFound() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); BrowseTree browseTree = new BrowseTree(mTestDevice); final String deviceId = browseTree.mRootNode.getID(); assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); } @Test public void setAndGetCurrentBrowsedPlayer() { BrowseTree browseTree = new BrowseTree(mTestDevice); Loading Loading
android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java +14 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.support.v4.media.MediaBrowserCompat.MediaItem; import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.flags.Flags; import com.google.common.annotations.VisibleForTesting; Loading Loading @@ -80,10 +81,22 @@ public class BrowseTree { mRootNode = new BrowseNode(new AvrcpItem.Builder() .setUuid(ROOT).setTitle(ROOT).setBrowsable(true).build()); mRootNode.setCached(true); } else { } else if (!Flags.randomizeDeviceLevelMediaIds()) { mRootNode = new BrowseNode(new AvrcpItem.Builder().setDevice(device) .setUuid(ROOT + device.getAddress().toString()) .setTitle(Utils.getName(device)).setBrowsable(true).build()); } else { mRootNode = new BrowseNode( new AvrcpItem.Builder() .setDevice(device) .setUuid( ROOT + device.getAddress().toString() + UUID.randomUUID().toString()) .setTitle(Utils.getName(device)) .setBrowsable(true) .build()); } mRootNode.mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST; Loading
android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java +58 −3 Original line number Diff line number Diff line Loading @@ -30,7 +30,9 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.media.AudioManager; import android.platform.test.flag.junit.SetFlagsRule; import android.support.v4.media.session.PlaybackStateCompat; import androidx.test.InstrumentationRegistry; Loading @@ -38,9 +40,12 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService.BrowseResult; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; import org.junit.After; import org.junit.Before; Loading @@ -61,6 +66,11 @@ import java.util.List; public class AvrcpControllerServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; private static final byte[] REMOTE_DEVICE_ADDRESS_AS_ARRAY = new byte[]{0, 0, 0, 0, 0, 0}; private static final String REMOTE_DEVICE_ADDRESS_2 = "11:11:11:11:11:11"; private static final byte[] REMOTE_DEVICE_ADDRESS_AS_ARRAY_2 = new byte[] {11, 11, 11, 11, 11, 11}; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private AvrcpControllerService mService = null; private BluetoothAdapter mAdapter = null; Loading @@ -70,11 +80,18 @@ public class AvrcpControllerServiceTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private A2dpSinkService mA2dpSinkService; @Mock private AdapterService mAdapterService; @Mock private AvrcpControllerStateMachine mStateMachine; @Mock private AvrcpControllerStateMachine mStateMachine2; @Mock private AvrcpControllerNativeInterface mNativeInterface; @Mock private Resources mMockResources; private BluetoothDevice mRemoteDevice; private BluetoothDevice mRemoteDevice2; @Mock private AvrcpControllerStateMachine mAvrcpStateMachine; @Before public void setUp() throws Exception { Loading @@ -86,17 +103,29 @@ public class AvrcpControllerServiceTest { // Try getting the Bluetooth adapter mAdapter = BluetoothAdapter.getDefaultAdapter(); assertThat(mAdapter).isNotNull(); // Set a mock A2dpSinkService for audio focus calls A2dpSinkService.setA2dpSinkService(mA2dpSinkService); when(mMockResources.getBoolean(R.bool.a2dp_sink_automatically_request_audio_focus)) .thenReturn(true); mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); mService.mDeviceStateMap.put(mRemoteDevice, mStateMachine); final Intent bluetoothBrowserMediaServiceStartIntent = TestUtils.prepareIntentToStartBluetoothBrowserMediaService(); mBluetoothBrowserMediaServiceTestRule.startService(bluetoothBrowserMediaServiceStartIntent); // Set up device and state machine under test mRemoteDevice2 = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS_2); mService.mDeviceStateMap.put(mRemoteDevice2, mStateMachine2); when(mA2dpSinkService.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true); } @After public void tearDown() throws Exception { mService.stop(); AvrcpControllerNativeInterface.setInstance(null); A2dpSinkService.setA2dpSinkService(null); mService = AvrcpControllerService.getAvrcpControllerService(); assertThat(mService).isNull(); TestUtils.clearAdapterService(mAdapterService); Loading Loading @@ -142,6 +171,7 @@ public class AvrcpControllerServiceTest { @Test public void setActiveDevice_whenA2dpSinkServiceIsNotInitailized_returnsFalse() { A2dpSinkService.setA2dpSinkService(null); assertThat(mService.setActiveDevice(mRemoteDevice)).isFalse(); assertThat(mService.getActiveDevice()).isNull(); Loading Loading @@ -465,7 +495,8 @@ public class AvrcpControllerServiceTest { mService.handleGetPlayerItemsRsp(mRemoteDevice, items); verify(mStateMachine).sendMessage( verify(mStateMachine) .sendMessage( eq(AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_PLAYER_ITEMS), eq(items)); } Loading @@ -487,4 +518,28 @@ public class AvrcpControllerServiceTest { mService.onAudioFocusStateChanged(AudioManager.AUDIOFOCUS_LOSS); assertThat(BluetoothMediaBrowserService.isActive()).isFalse(); } /** * Connect first device and check that it is the active device. Pair a second device, then * disconnect and repair this known second device. Confirm that audio focus is maintained by * first device by checking that it has remained as the active device. */ @Test public void testActiveDeviceMaintainsAudioFocusWhenOtherDeviceConnects_audioFocusMaintained() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); mService.onConnectionStateChanged(true, true, mRemoteDevice); // check set active device is called verify(mA2dpSinkService).setActiveDevice(mRemoteDevice); when(mA2dpSinkService.getActiveDevice()).thenReturn(mRemoteDevice); // connect another phone mService.onConnectionStateChanged(true, true, mRemoteDevice2); verify(mA2dpSinkService, times(0)).setActiveDevice(mRemoteDevice2); // disconnect and reconnect other phone mService.onConnectionStateChanged(false, false, mRemoteDevice2); mService.onConnectionStateChanged(true, true, mRemoteDevice2); verify(mA2dpSinkService, times(0)).setActiveDevice(mRemoteDevice2); } }
android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +46 −34 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.bluetooth.avrcpcontroller; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; Loading @@ -29,6 +31,7 @@ import android.content.res.Resources; import android.media.AudioManager; import android.os.Bundle; import android.os.Looper; import android.platform.test.flag.junit.SetFlagsRule; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; Loading @@ -44,6 +47,7 @@ import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; import org.hamcrest.core.IsInstanceOf; import org.junit.After; Loading @@ -68,6 +72,10 @@ public class AvrcpControllerStateMachineTest { private static final int CONNECT_TIMEOUT_TEST_MILLIS = 1000; private static final int KEY_DOWN = 0; private static final int KEY_UP = 1; private static final int UUID_START = 0; private static final int UUID_LENGTH = 25; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private BluetoothAdapter mAdapter; Loading Loading @@ -135,6 +143,7 @@ public class AvrcpControllerStateMachineTest { // Set up device and state machine under test mTestDevice = mAdapter.getRemoteDevice(mTestAddress); mAvrcpStateMachine = makeStateMachine(mTestDevice); setActiveDevice(mTestDevice); } Loading Loading @@ -461,6 +470,27 @@ public class AvrcpControllerStateMachineTest { verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine)); } /** Get the root of the device */ @Test public void testGetDeviceRootNode_flagRandomDeviceIdDisabled_rootNodeMatchesUuidFormat() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); } /** Get the root of the device */ @Test public void testGetDeviceRootNode_flagRandomDeviceIdEnabled_rootNodeMatchesUuidFormat() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; assertThat((results.getID()).substring(UUID_START, UUID_LENGTH)).isEqualTo(rootName); } /** * Test to make sure the state machine is tracking the correct device */ Loading Loading @@ -716,12 +746,8 @@ public class AvrcpControllerStateMachineTest { @FlakyTest public void testBrowsingCommands() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); final String playerName = "Player 1"; //Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID()); Loading Loading @@ -764,14 +790,13 @@ public class AvrcpControllerStateMachineTest { @Test public void testAvailablePlayersChanged() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Send an available players have changed event mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED); // Verify we've uncached our browse root and made the call to fetch new players Assert.assertFalse(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertFalse(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getPlayerList(eq(mTestAddress), eq(0), eq(19)); } Loading @@ -783,7 +808,6 @@ public class AvrcpControllerStateMachineTest { @Test public void testAvailablePlayersReceived_AddressedPlayerExists() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Set an addressed player that will be in the available players set. A new player triggers // a now playing list download, so send back nothing. Loading @@ -801,7 +825,7 @@ public class AvrcpControllerStateMachineTest { AvrcpControllerStateMachine.MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED); // Verify we've uncached our browse root and made the call to fetch new players Assert.assertFalse(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertFalse(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getPlayerList(eq(mTestAddress), eq(0), eq(19)); Loading @@ -821,7 +845,7 @@ public class AvrcpControllerStateMachineTest { // Verify we processed the first players properly. Note the addressed player should always // be in the available player set. Assert.assertTrue(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertTrue(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); Assert.assertTrue(players.contains(mAvrcpStateMachine.getAddressedPlayerId())); Assert.assertEquals(testPlayers.size(), players.size()); Loading @@ -846,14 +870,13 @@ public class AvrcpControllerStateMachineTest { @Test public void testAvailablePlayersReceived_AddressedPlayerDoesNotExist() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Send an available players have changed event mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED); // Verify we've uncached our browse root and made the call to fetch new players Assert.assertFalse(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertFalse(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getPlayerList(eq(mTestAddress), eq(0), eq(19)); Loading @@ -874,7 +897,7 @@ public class AvrcpControllerStateMachineTest { // Verify we processed the players properly. Note the addressed player is currently the // default player and is not in the available player set sent. This means we'll have an // extra player at ID -1. Assert.assertTrue(mAvrcpStateMachine.findNode(rootName).isCached()); Assert.assertTrue(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); Assert.assertTrue(players.contains(mAvrcpStateMachine.getAddressedPlayerId())); Assert.assertEquals(testPlayers.size() + 1, players.size()); Loading @@ -899,11 +922,8 @@ public class AvrcpControllerStateMachineTest { @Test public void testAddressedPlayerChangedToNewKnownPlayer() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID()); Loading Loading @@ -962,11 +982,9 @@ public class AvrcpControllerStateMachineTest { @Test public void testAddressedPlayerChangedToUnknownPlayer() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Get the root of the device BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, rootNode.getID()); BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(rootNode.getID()); Loading Loading @@ -1009,7 +1027,6 @@ public class AvrcpControllerStateMachineTest { @Test public void testAddressedPlayerChangedToSamePlayerId() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); // Set the addressed player so we can change to the same one mAvrcpStateMachine.sendMessage( Loading @@ -1022,8 +1039,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Get the root of the device BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, rootNode.getID()); BrowseTree.BrowseNode rootNode = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(rootNode.getID()); Loading Loading @@ -1080,12 +1096,10 @@ public class AvrcpControllerStateMachineTest { @Test public void testPlayWhileBrowsing() { setUpConnectedState(true, true); final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); final String playerName = "Player 1"; // Get the root of the device BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName); Assert.assertEquals(rootName, results.getID()); BrowseTree.BrowseNode results = mAvrcpStateMachine.mBrowseTree.mRootNode; //Request fetch the list of players BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID()); Loading Loading @@ -2083,12 +2097,11 @@ public class AvrcpControllerStateMachineTest { */ @Test public void testBrowseRequestWhileDisconnected_requestDropped() { final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); setUpConnectedState(true, false); sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_GAIN); clearInvocations(mAvrcpControllerService); clearInvocations(mNativeInterface); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.findNode(rootName); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.mBrowseTree.mRootNode; mAvrcpStateMachine.requestContents(deviceRoot); TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); verifyNoMoreInteractions(mAvrcpControllerService); Loading @@ -2101,12 +2114,11 @@ public class AvrcpControllerStateMachineTest { */ @Test public void testBrowseRequestWhileDisconnectedThenRequestWhileConnected_secondRequestSent() { final String rootName = "__ROOT__" + mTestDevice.getAddress().toString(); setUpConnectedState(true, false); sendAudioFocusUpdate(AudioManager.AUDIOFOCUS_GAIN); clearInvocations(mAvrcpControllerService); clearInvocations(mNativeInterface); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.findNode(rootName); BrowseTree.BrowseNode deviceRoot = mAvrcpStateMachine.mBrowseTree.mRootNode; mAvrcpStateMachine.requestContents(deviceRoot); // issues a player list fetch mAvrcpStateMachine.connect(StackEvent.connectionStateChanged(true, true)); Loading
android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java +33 −0 Original line number Diff line number Diff line Loading @@ -20,10 +20,13 @@ import static com.google.common.truth.Truth.assertThat; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.platform.test.flag.junit.SetFlagsRule; import com.android.bluetooth.avrcpcontroller.BrowseTree.BrowseNode; import com.android.bluetooth.flags.Flags; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import java.util.Set; Loading @@ -33,6 +36,8 @@ public class BrowseTreeTest { private static final String TEST_HANDLE = "test_handle"; private static final String TEST_NODE_ID = "test_node_id"; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private final byte[] mTestAddress = new byte[]{01, 01, 01, 01, 01, 01}; private BluetoothAdapter mAdapter; private BluetoothDevice mTestDevice = null; Loading Loading @@ -89,6 +94,18 @@ public class BrowseTreeTest { assertThat(browseTree.mRootNode.getChildrenCount()).isEqualTo(1); } @Test public void sameDeviceDifferentBrowseTrees_uniqueMediaIds() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); BrowseTree browseTree1 = new BrowseTree(mTestDevice); BrowseTree browseTree2 = new BrowseTree(mTestDevice); String mediaId1 = browseTree1.mRootNode.getID(); String mediaId2 = browseTree2.mRootNode.getID(); assertThat(mediaId1).isNotEqualTo(mediaId2); } @Test public void findBrowseNodeByIDForRoot() { BrowseTree browseTree = new BrowseTree(null); Loading @@ -102,6 +119,14 @@ public class BrowseTreeTest { assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); } @Test public void findBrowseNodeByIDForDevice_flagEnabled() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); BrowseTree browseTree = new BrowseTree(mTestDevice); final String deviceId = browseTree.mRootNode.getID(); assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); } @Test public void findBrowseNodeByIDForIllegalId() { BrowseTree browseTree = new BrowseTree(mTestDevice); Loading @@ -117,6 +142,14 @@ public class BrowseTreeTest { assertThat(browseTree.getCurrentBrowsedFolder()).isEqualTo(browseTree.mNowPlayingNode); } @Test public void findBrowseNodeByIDForDevice_withRandomDeviceID_nodeIsFound() { mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS); BrowseTree browseTree = new BrowseTree(mTestDevice); final String deviceId = browseTree.mRootNode.getID(); assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode); } @Test public void setAndGetCurrentBrowsedPlayer() { BrowseTree browseTree = new BrowseTree(mTestDevice); Loading