Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60665892 authored by Joseph Pirozzo's avatar Joseph Pirozzo
Browse files

AVRCP Controller addressed player changed

When the remote device addressed player changes, the browsing tree
should be updated to reflect the new content.  This is specifically for
devices that only support a single browsable/addressed player.

Bug: 133508789
Test: atest com.android.bluetooth.avrcpcontroller.AvrcpControllerStateMachineTest
Change-Id: I4a47d83cb5c21f66b0805f71c96f713e38540ed1
parent 85e395f9
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ class AvrcpControllerStateMachine extends StateMachine {
    boolean mBrowsingConnected = false;
    BrowseTree mBrowseTree = null;
    private AvrcpPlayer mAddressedPlayer = new AvrcpPlayer();
    private int mAddressedPlayerId = -1;
    private SparseArray<AvrcpPlayer> mAvailablePlayerList = new SparseArray<AvrcpPlayer>();
    private int mVolumeChangedNotificationsToIgnore = 0;

@@ -347,6 +348,20 @@ class AvrcpControllerStateMachine extends StateMachine {
                    }
                    return true;

                case MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED:
                    mAddressedPlayerId = msg.arg1;
                    logD("AddressedPlayer = " + mAddressedPlayerId);
                    AvrcpPlayer updatedPlayer = mAvailablePlayerList.get(mAddressedPlayerId);
                    if (updatedPlayer != null) {
                        mAddressedPlayer = updatedPlayer;
                        logD("AddressedPlayer = " + mAddressedPlayer.getName());
                    } else {
                        mBrowseTree.mRootNode.setCached(false);
                        mBrowseTree.mRootNode.setExpectedChildren(255);
                        BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mRootNode);
                    }
                    return true;

                case DISCONNECT:
                    transitionTo(mDisconnecting);
                    return true;
@@ -522,8 +537,8 @@ class AvrcpControllerStateMachine extends StateMachine {

                case MESSAGE_GET_FOLDER_ITEMS:
                    if (!mBrowseNode.equals(msg.obj)) {
                        if (mBrowseNode.getScope()
                                == ((BrowseTree.BrowseNode) msg.obj).getScope()) {
                        if (shouldAbort(mBrowseNode.getScope(),
                                 ((BrowseTree.BrowseNode) msg.obj).getScope())) {
                            mAbort = true;
                        }
                        deferMessage(msg);
@@ -543,6 +558,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
                case MESSAGE_PROCESS_VOLUME_CHANGED_NOTIFICATION:
                case MESSAGE_PLAY_ITEM:
                case MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED:
                    // All of these messages should be handled by parent state immediately.
                    return false;

@@ -554,6 +570,23 @@ class AvrcpControllerStateMachine extends StateMachine {
            return true;
        }

        /**
         * shouldAbort calculates the cases where fetching the current directory is no longer
         * necessary.
         *
         * @return true:  a new folder in the same scope
         *                a new player while fetching contents of a folder
         *         false: other cases, specifically Now Playing while fetching a folder
         */
        private boolean shouldAbort(int currentScope, int fetchScope) {
            if ((currentScope == fetchScope)
                    || (currentScope == AvrcpControllerService.BROWSE_SCOPE_VFS
                    && fetchScope == AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST)) {
                return true;
            }
            return false;
        }

        private void fetchContents(BrowseTree.BrowseNode target) {
            int start = target.getChildrenCount();
            int end = Math.min(target.getExpectedChildren(), target.getChildrenCount()
+2 −1
Original line number Diff line number Diff line
@@ -412,7 +412,8 @@ public class BrowseTree {
        if (target == null) {
            return null;
        } else if (target.equals(mCurrentBrowseNode)
                || target.equals(mNowPlayingNode)) {
                || target.equals(mNowPlayingNode)
                || target.equals(mRootNode)) {
            return target;
        } else if (target.isPlayer()) {
            if (mDepth > 0) {
+43 −0
Original line number Diff line number Diff line
@@ -403,6 +403,49 @@ public class AvrcpControllerStateMachineTest {
                eq(0), eq(4));
    }

    /**
     * Test addressed media player changed
     * Verify when the addressed media player changes browsing data updates
     * Verify that the contents of a player are fetched upon request
     */
    @Test
    public void testPlayerChanged() {
        setUpConnectedState(true, true);
        final String rootName = "__ROOT__";
        final String playerName = "Player 1";

        //Get the root of the device
        BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName);
        Assert.assertEquals(rootName + mTestDevice.toString(), results.getID());

        //Request fetch the list of players
        BrowseTree.BrowseNode playerNodes = mAvrcpStateMachine.findNode(results.getID());
        mAvrcpStateMachine.requestContents(results);
        verify(mAvrcpControllerService,
                timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)).getPlayerListNative(eq(mTestAddress),
                eq(0), eq(19));

        //Provide back a player object
        byte[] playerFeatures =
                new byte[]{0, 0, 0, 0, 0, (byte) 0xb7, 0x01, 0x0c, 0x0a, 0, 0, 0, 0, 0, 0, 0};
        AvrcpPlayer playerOne = new AvrcpPlayer(1, playerName, playerFeatures, 1, 1);
        List<AvrcpPlayer> testPlayers = new ArrayList<>();
        testPlayers.add(playerOne);
        mAvrcpStateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_PLAYER_ITEMS,
                testPlayers);

        //Change players and verify that BT attempts to update the results
        mAvrcpStateMachine.sendMessage(
                AvrcpControllerStateMachine.MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED, 4);
        results = mAvrcpStateMachine.findNode(rootName);

        mAvrcpStateMachine.requestContents(results);

        verify(mAvrcpControllerService,
                timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)).getPlayerListNative(eq(mTestAddress),
                eq(0), eq(19));
    }

    /**
     * Test that the Now Playing playlist is updated when it changes.
     */