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

Commit fe642416 authored by Sal Savage's avatar Sal Savage
Browse files

Create an AvrcpPlayer.Builder to consolidate constructors

This change creates a builder object for out AvrcpPlayer so we can have
greater flexibility in how we create the object without needing to
support several different types of constructors. The intent is to use
this in a follow up patch.

Tag: #stability
Bug: 187107189
Test: atest BluetoothInstrumentationTests
Change-Id: I0221ab61350c2ea446b97a74dcfe8c975ce311d2
parent 1636ca0c
Loading
Loading
Loading
Loading
+35 −24
Original line number Diff line number Diff line
@@ -222,6 +222,30 @@ public class AvrcpControllerService extends ProfileService {
        return false;
    }

    private int toPlaybackStateFromJni(int fromJni) {
        int playbackState = PlaybackStateCompat.STATE_NONE;
        switch (fromJni) {
            case JNI_PLAY_STATUS_STOPPED:
                playbackState = PlaybackStateCompat.STATE_STOPPED;
                break;
            case JNI_PLAY_STATUS_PLAYING:
                playbackState = PlaybackStateCompat.STATE_PLAYING;
                break;
            case JNI_PLAY_STATUS_PAUSED:
                playbackState = PlaybackStateCompat.STATE_PAUSED;
                break;
            case JNI_PLAY_STATUS_FWD_SEEK:
                playbackState = PlaybackStateCompat.STATE_FAST_FORWARDING;
                break;
            case JNI_PLAY_STATUS_REV_SEEK:
                playbackState = PlaybackStateCompat.STATE_REWINDING;
                break;
            default:
                playbackState = PlaybackStateCompat.STATE_NONE;
        }
        return playbackState;
    }

    protected AvrcpControllerStateMachine newStateMachine(BluetoothDevice device) {
        return new AvrcpControllerStateMachine(device, this);
    }
@@ -530,31 +554,12 @@ public class AvrcpControllerService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "onPlayStatusChanged " + playStatus);
        }
        int playbackState = PlaybackStateCompat.STATE_NONE;
        switch (playStatus) {
            case JNI_PLAY_STATUS_STOPPED:
                playbackState = PlaybackStateCompat.STATE_STOPPED;
                break;
            case JNI_PLAY_STATUS_PLAYING:
                playbackState = PlaybackStateCompat.STATE_PLAYING;
                break;
            case JNI_PLAY_STATUS_PAUSED:
                playbackState = PlaybackStateCompat.STATE_PAUSED;
                break;
            case JNI_PLAY_STATUS_FWD_SEEK:
                playbackState = PlaybackStateCompat.STATE_FAST_FORWARDING;
                break;
            case JNI_PLAY_STATUS_REV_SEEK:
                playbackState = PlaybackStateCompat.STATE_REWINDING;
                break;
            default:
                playbackState = PlaybackStateCompat.STATE_NONE;
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        AvrcpControllerStateMachine stateMachine = getStateMachine(device);
        if (stateMachine != null) {
            stateMachine.sendMessage(
                    AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED, playbackState);
                    AvrcpControllerStateMachine.MESSAGE_PROCESS_PLAY_STATUS_CHANGED,
                    toPlaybackStateFromJni(playStatus));
        }
    }

@@ -698,10 +703,16 @@ public class AvrcpControllerService extends ProfileService {
                            + transportFlags + " play status " + playStatus + " player type "
                            + playerType);
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        AvrcpPlayer player = new AvrcpPlayer(device, id, name, transportFlags, playStatus,
                playerType);
        return player;
        AvrcpPlayer.Builder apb = new AvrcpPlayer.Builder();
        apb.setDevice(device);
        apb.setPlayerId(id);
        apb.setPlayerType(playerType);
        apb.setSupportedFeatures(transportFlags);
        apb.setName(name);
        apb.setPlayStatus(toPlaybackStateFromJni(playStatus));
        return apb.build();
    }

    private void handleChangeFolderRsp(byte[] address, int count) {
+14 −2
Original line number Diff line number Diff line
@@ -126,8 +126,8 @@ class AvrcpControllerStateMachine extends StateMachine {
    boolean mRemoteControlConnected = false;
    boolean mBrowsingConnected = false;
    final BrowseTree mBrowseTree;
    private AvrcpPlayer mAddressedPlayer = new AvrcpPlayer();
    private int mAddressedPlayerId = -1;
    private AvrcpPlayer mAddressedPlayer;
    private int mAddressedPlayerId;
    private SparseArray<AvrcpPlayer> mAvailablePlayerList = new SparseArray<AvrcpPlayer>();
    private int mVolumeChangedNotificationsToIgnore = 0;
    private int mVolumeNotificationLabel = -1;
@@ -148,6 +148,18 @@ class AvrcpControllerStateMachine extends StateMachine {
        mCoverArtManager = service.getCoverArtManager();
        logD(device.toString());

        mAddressedPlayerId = AvrcpPlayer.DEFAULT_ID;

        AvrcpPlayer.Builder apb = new AvrcpPlayer.Builder();
        apb.setDevice(mDevice);
        apb.setPlayerId(mAddressedPlayerId);
        apb.setSupportedFeature(AvrcpPlayer.FEATURE_PLAY);
        apb.setSupportedFeature(AvrcpPlayer.FEATURE_PAUSE);
        apb.setSupportedFeature(AvrcpPlayer.FEATURE_STOP);
        apb.setSupportedFeature(AvrcpPlayer.FEATURE_FORWARD);
        apb.setSupportedFeature(AvrcpPlayer.FEATURE_PREVIOUS);
        mAddressedPlayer = apb.build();

        mBrowseTree = new BrowseTree(mDevice);
        mDisconnected = new Disconnected();
        mConnecting = new Connecting();
+145 −17
Original line number Diff line number Diff line
@@ -32,7 +32,17 @@ class AvrcpPlayer {
    private static final String TAG = "AvrcpPlayer";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);

    public static final int INVALID_ID = -1;
    public static final int DEFAULT_ID = -1;

    public static final int TYPE_UNKNOWN = -1;
    public static final int TYPE_AUDIO = 0;
    public static final int TYPE_VIDEO = 1;
    public static final int TYPE_BROADCASTING_AUDIO = 2;
    public static final int TYPE_BROADCASTING_VIDEO = 3;

    public static final int SUB_TYPE_UNKNOWN = -1;
    public static final int SUB_TYPE_AUDIO_BOOK = 0;
    public static final int SUB_TYPE_PODCAST = 1;

    public static final int FEATURE_PLAY = 40;
    public static final int FEATURE_STOP = 41;
@@ -60,21 +70,8 @@ class AvrcpPlayer {
            new PlayerApplicationSettings();
    private PlayerApplicationSettings mCurrentPlayerApplicationSettings;

    AvrcpPlayer() {
        mDevice = null;
        mId = INVALID_ID;
        //Set Default Actions in case Player data isn't available.
        mAvailableActions = PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY
                | PlaybackStateCompat.ACTION_SKIP_TO_NEXT
                | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
                | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_PREPARE;
        PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder()
                .setActions(mAvailableActions);
        mPlaybackStateCompat = playbackStateBuilder.build();
    }

    AvrcpPlayer(BluetoothDevice device, int id, String name, byte[] playerFeatures, int playStatus,
            int playerType) {
    private AvrcpPlayer(BluetoothDevice device, int id, int playerType, int playerSubType,
            String name, byte[] playerFeatures, int playStatus) {
        mDevice = device;
        mId = id;
        mName = name;
@@ -204,6 +201,7 @@ class AvrcpPlayer {
    }

    private void updateAvailableActions() {
        mAvailableActions = PlaybackStateCompat.ACTION_PREPARE;
        if (supportsFeature(FEATURE_PLAY)) {
            mAvailableActions = mAvailableActions | PlaybackStateCompat.ACTION_PLAY;
        }
@@ -242,6 +240,136 @@ class AvrcpPlayer {
    @Override
    public String toString() {
        return "<AvrcpPlayer id=" + mId + " name=" + mName + " track=" + mCurrentTrack
                + " play_status=" + mPlayStatus + ">";
                + " playState=" + mPlaybackStateCompat + ">";
    }

    /**
     * A Builder object for an AvrcpPlayer
     */
    public static class Builder {
        private static final String TAG = "AvrcpPlayer.Builder";
        private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);

        private BluetoothDevice mDevice = null;
        private int mPlayerId = AvrcpPlayer.DEFAULT_ID;
        private int mPlayerType = AvrcpPlayer.TYPE_UNKNOWN;
        private int mPlayerSubType = AvrcpPlayer.SUB_TYPE_UNKNOWN;
        private String mPlayerName = null;
        private byte[] mSupportedFeatures = new byte[16];

        private int mPlayStatus = PlaybackStateCompat.STATE_NONE;
        private long mPlayTime = PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN;
        private float mPlaySpeed = 1;
        private long mPlayTimeUpdate = 0;

        private AvrcpItem mTrack = null;

        /**
         * Set the device that this Player came from
         *
         * @param device The BleutoothDevice representing the remote device
         * @return This object, so you can continue building
         */
        public Builder setDevice(BluetoothDevice device) {
            mDevice = device;
            return this;
        }

        /**
         * Set the Player ID for this Player
         *
         * @param playerId The ID for this player, defined in AVRCP 6.10.2.1
         * @return This object, so you can continue building
         */
        public Builder setPlayerId(int playerId) {
            mPlayerId = playerId;
            return this;
        }

        /**
         * Set the Player Type for this Player
         *
         * @param playerType The type for this player, defined in AVRCP 6.10.2.1
         * @return This object, so you can continue building
         */
        public Builder setPlayerType(int playerType) {
            mPlayerType = playerType;
            return this;
        }

        /**
         * Set the Player Sub-type for this Player
         *
         * @param playerSubType The sub-type for this player, defined in AVRCP 6.10.2.1
         * @return This object, so you can continue building
         */
        public Builder setPlayerSubType(int playerSubType) {
            mPlayerSubType = playerSubType;
            return this;
        }

        /**
         * Set the name for this Player. This is what users will see when browsing.
         *
         * @param name The name for this player, defined in AVRCP 6.10.2.1
         * @return This object, so you can continue building
         */
        public Builder setName(String name) {
            mPlayerName = name;
            return this;
        }

        /**
         * Set the entire set of supported features for this Player.
         *
         * @param features The feature set for this player, defined in AVRCP 6.10.2.1
         * @return This object, so you can continue building
         */
        public Builder setSupportedFeatures(byte[] supportedFeatures) {
            mSupportedFeatures = supportedFeatures;
            return this;
        }

        /**
         * Set a single features as supported for this Player.
         *
         * @param feature The feature for this player, defined in AVRCP 6.10.2.1
         * @return This object, so you can continue building
         */
        public Builder setSupportedFeature(int feature) {
            int byteNumber = feature / 8;
            byte bitMask = (byte) (1 << (feature % 8));
            mSupportedFeatures[byteNumber] = (byte) (mSupportedFeatures[byteNumber] | bitMask);
            return this;
        }

        /**
         * Set the initial play status of the Player.
         *
         * @param playStatus The play state for this player as a PlaybackStateCompat.STATE_* value
         * @return This object, so you can continue building
         */
        public Builder setPlayStatus(int playStatus) {
            mPlayStatus = playStatus;
            return this;
        }

        /**
         * Set the initial play status of the Player.
         *
         * @param track The initial track for this player
         * @return This object, so you can continue building
         */
        public Builder setCurrentTrack(AvrcpItem track) {
            mTrack = track;
            return this;
        }

        public AvrcpPlayer build() {
            AvrcpPlayer player = new AvrcpPlayer(mDevice, mPlayerId, mPlayerType, mPlayerSubType,
                    mPlayerName, mSupportedFeatures, mPlayStatus);
            player.updateCurrentTrack(mTrack);
            return player;
        }
    }
}
+16 −4
Original line number Diff line number Diff line
@@ -229,6 +229,18 @@ public class AvrcpControllerStateMachineTest {
        return builder.build();
    }

    private AvrcpPlayer makePlayer(BluetoothDevice device, int playerId, String playerName,
            int playerType, byte[] playerFeatures, int playStatus) {
        AvrcpPlayer.Builder apb = new AvrcpPlayer.Builder();
        apb.setDevice(device);
        apb.setPlayerId(playerId);
        apb.setName(playerName);
        apb.setPlayerType(playerType);
        apb.setSupportedFeatures(playerFeatures);
        apb.setPlayStatus(playStatus);
        return apb.build();
    }

    /**
     * Send a message to the state machine that the track has changed. Must be connected to
     * do this.
@@ -674,7 +686,7 @@ public class AvrcpControllerStateMachineTest {
        //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(mTestDevice, 1, playerName, playerFeatures, 1, 1);
        AvrcpPlayer playerOne = makePlayer(mTestDevice, 1, playerName, 1, playerFeatures, 1);
        List<AvrcpPlayer> testPlayers = new ArrayList<>();
        testPlayers.add(playerOne);
        mAvrcpStateMachine.sendMessage(AvrcpControllerStateMachine.MESSAGE_PROCESS_GET_PLAYER_ITEMS,
@@ -749,8 +761,8 @@ public class AvrcpControllerStateMachineTest {
        //Provide back two player objects, IDs 1 and 2
        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(mTestDevice, 1, "Player 1", playerFeatures, 1, 1);
        AvrcpPlayer playerTwo = new AvrcpPlayer(mTestDevice, 2, "Player 2", playerFeatures, 1, 1);
        AvrcpPlayer playerOne = makePlayer(mTestDevice, 1, "Player 1", 1, playerFeatures, 1);
        AvrcpPlayer playerTwo = makePlayer(mTestDevice, 2, "Player 2", 1, playerFeatures, 1);
        List<AvrcpPlayer> testPlayers = new ArrayList<>();
        testPlayers.add(playerOne);
        testPlayers.add(playerTwo);
@@ -802,7 +814,7 @@ public class AvrcpControllerStateMachineTest {
        //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(mTestDevice, 1, "Player 1", playerFeatures, 1, 1);
        AvrcpPlayer playerOne = makePlayer(mTestDevice, 1, "Player 1", 1, playerFeatures, 1);
        List<AvrcpPlayer> testPlayers = new ArrayList<>();
        testPlayers.add(playerOne);
        mAvrcpStateMachine.sendMessage(