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

Commit 24935b2d authored by Marie Janssen's avatar Marie Janssen Committed by android-build-merger
Browse files

Avrcp: Limit available players changed

am: 04bcb869

Change-Id: Iedc3d249ea37e10133ea93f28523e68f54ac03f7
parents c23fb6fd 04bcb869
Loading
Loading
Loading
Loading
+49 −42
Original line number Diff line number Diff line
@@ -161,9 +161,8 @@ public final class Avrcp {
    private static final int MSG_SET_ABSOLUTE_VOLUME = 16;
    private static final int MSG_ABS_VOL_TIMEOUT = 17;
    private static final int MSG_SET_A2DP_AUDIO_STATE = 18;
    private static final int MSG_AVAILABLE_PLAYERS_CHANGED_RSP = 19;
    private static final int MSG_NOW_PLAYING_CHANGED_RSP = 20;
    private static final int MSG_UPDATE_MEDIA = 21;
    private static final int MSG_NOW_PLAYING_CHANGED_RSP = 19;
    private static final int MSG_UPDATE_MEDIA = 20;

    private static final int CMD_TIMEOUT_DELAY = 2000;
    private static final int MEDIA_DWELL_TIME = 1000;
@@ -179,6 +178,7 @@ public final class Avrcp {

    /* List of Media player instances, useful for retrieving MediaPlayerList or MediaPlayerInfo */
    private SortedMap<Integer, MediaPlayerInfo> mMediaPlayerInfoList;
    private boolean mAvailablePlayerViewChanged;

    /* List of media players which supports browse */
    private List<BrowsePlayerInfo> mBrowsePlayerInfoList;
@@ -304,6 +304,7 @@ public final class Avrcp {
        mMediaControllerCb = new MediaControllerListener();
        mAvrcpMediaRsp = new AvrcpMediaRsp();
        mMediaPlayerInfoList = new TreeMap<Integer, MediaPlayerInfo>();
        mAvailablePlayerViewChanged = false;
        mBrowsePlayerInfoList = Collections.synchronizedList(new ArrayList<BrowsePlayerInfo>());
        mPassthroughDispatched = 0;
        mPassthroughLogs = new EvictingQueue<MediaKeyLog>(PASSTHROUGH_LOG_MAX_SIZE);
@@ -474,13 +475,6 @@ public final class Avrcp {
                processRegisterNotification((byte[]) msg.obj, msg.arg1, msg.arg2);
                break;

            case MSG_AVAILABLE_PLAYERS_CHANGED_RSP:
                if (DEBUG) Log.v(TAG, "MSG_AVAILABLE_PLAYERS_CHANGED_RSP");
                removeMessages(MSG_AVAILABLE_PLAYERS_CHANGED_RSP);
                registerNotificationRspAvalPlayerChangedNative(
                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
                break;

            case MSG_NOW_PLAYING_CHANGED_RSP:
                if (DEBUG) Log.v(TAG, "MSG_NOW_PLAYING_CHANGED_RSP");
                removeMessages(MSG_NOW_PLAYING_CHANGED_RSP);
@@ -986,12 +980,19 @@ public final class Avrcp {
    }

    private void updateCurrentMediaState(boolean registering) {
        if (!registering && mAddrPlayerChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM
        // Only do player updates when we aren't registering for track changes.
        if (!registering) {
            if (mAvailablePlayerViewChanged) {
                registerNotificationRspAvalPlayerChangedNative(
                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
                mAvailablePlayerViewChanged = false;
            }
            if (mAddrPlayerChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM
                    && mReportedPlayerID != mCurrAddrPlayerID) {
                registerNotificationRspAddrPlayerChangedNative(
                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED, mCurrAddrPlayerID, sUIDCounter);
                mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
            // Changing player sends reject to all these, so disable them.
                // Changing player sends reject to anything else we would notify...
                mReportedPlayerID = mCurrAddrPlayerID;
                mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
                mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
@@ -1000,6 +1001,7 @@ public final class Avrcp {
                // so we can skip the rest of the update.
                return;
            }
        }

        MediaAttributes currentAttributes;
        PlaybackState newState = updatePlaybackState();
@@ -1580,23 +1582,17 @@ public final class Avrcp {
                @Override
                public void onActiveSessionsChanged(
                        List<android.media.session.MediaController> newControllers) {
                    boolean playersChanged = false;

                    // Update the current players
                    for (android.media.session.MediaController controller : newControllers) {
                        addMediaPlayerController(controller);
                        playersChanged = true;
                    }

                    if (playersChanged) {
                        mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP);
                    if (newControllers.size() > 0 && getAddressedPlayerInfo() == null) {
                        if (DEBUG)
                                Log.v(TAG,
                                        "No addressed player but active sessions, taking first.");
                            Log.v(TAG, "No addressed player but active sessions, taking first.");
                        setAddressedMediaSessionPackage(newControllers.get(0).getPackageName());
                    }
                    }
                    scheduleMediaUpdate();
                }
            };

@@ -1612,7 +1608,7 @@ public final class Avrcp {
        // If the player doesn't exist, we need to add it.
        if (getMediaPlayerInfo(packageName) == null) {
            addMediaPlayerPackage(packageName);
            mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP);
            scheduleMediaUpdate();
        }
        synchronized (mMediaPlayerInfoList) {
            for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) {
@@ -1758,9 +1754,8 @@ public final class Avrcp {
            for (android.media.session.MediaController controller : controllers) {
                addMediaPlayerController(controller);
            }
            if (controllers.size() > 0) {
                mHandler.sendEmptyMessage(MSG_AVAILABLE_PLAYERS_CHANGED_RSP);
            }

            scheduleMediaUpdate();

            if (mMediaPlayerInfoList.size() > 0) {
                // Set the first one as the Addressed Player
@@ -1808,10 +1803,20 @@ public final class Avrcp {
    private boolean addMediaPlayerInfo(MediaPlayerInfo info) {
        int updateId = -1;
        boolean updated = false;
        boolean currentRemoved = false;
        synchronized (mMediaPlayerInfoList) {
            for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) {
                if (info.getPackageName().equals(entry.getValue().getPackageName())) {
                    updateId = entry.getKey();
                MediaPlayerInfo current = entry.getValue();
                int id = entry.getKey();
                if (info.getPackageName().equals(current.getPackageName())) {
                    if (!current.equalView(info)) {
                        // If we would present a different player, make it a new player
                        // so that controllers know whether a player is browsable or not.
                        mMediaPlayerInfoList.remove(id);
                        currentRemoved = (mCurrAddrPlayerID == id);
                        break;
                    }
                    updateId = id;
                    updated = true;
                    break;
                }
@@ -1820,12 +1825,13 @@ public final class Avrcp {
                // New player
                mLastUsedPlayerID++;
                updateId = mLastUsedPlayerID;
                mAvailablePlayerViewChanged = true;
            }
            mMediaPlayerInfoList.put(updateId, info);
            if (DEBUG)
                Log.d(TAG, (updated ? "update #" : "add #") + updateId + ":" + info.toString());
            if (updateId == mCurrAddrPlayerID) {
                updateCurrentController(mCurrAddrPlayerID, mCurrBrowsePlayerID);
            if (currentRemoved || updateId == mCurrAddrPlayerID) {
                updateCurrentController(updateId, mCurrBrowsePlayerID);
            }
        }
        return updated;
@@ -1844,6 +1850,7 @@ public final class Avrcp {
            if (removeKey != -1) {
                if (DEBUG)
                    Log.d(TAG, "remove #" + removeKey + ":" + mMediaPlayerInfoList.get(removeKey));
                mAvailablePlayerViewChanged = true;
                return mMediaPlayerInfoList.remove(removeKey);
            }

+21 −7
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.bluetooth.avrcp;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.media.session.MediaSession;

import com.android.bluetooth.Utils;
@@ -200,17 +202,19 @@ class MediaPlayerInfo {
    private int subType;
    private byte playStatus;
    private short[] featureBitMask;
    private String packageName;
    private String displayableName;
    private MediaController mediaController;
    private @NonNull String packageName;
    private @NonNull String displayableName;
    private @Nullable MediaController mediaController;

    MediaPlayerInfo(MediaController controller, byte majorType, int subType, byte playStatus,
            short[] featureBitMask, String packageName, String displayableName) {
    MediaPlayerInfo(@Nullable MediaController controller, byte majorType, int subType,
            byte playStatus, short[] featureBitMask, @NonNull String packageName,
            @Nullable String displayableName) {
        this.setMajorType(majorType);
        this.setSubType(subType);
        this.playStatus = playStatus;
        // store a copy the FeatureBitMask array
        this.featureBitMask = Arrays.copyOf(featureBitMask, featureBitMask.length);
        Arrays.sort(this.featureBitMask);
        this.setPackageName(packageName);
        this.setDisplayableName(displayableName);
        this.setMediaController(controller);
@@ -236,7 +240,7 @@ class MediaPlayerInfo {
        this.mediaController = mediaController;
    }

    void setPackageName(String name) {
    void setPackageName(@NonNull String name) {
        // Controller determines package name when it is set.
        if (mediaController != null) return;
        this.packageName = name;
@@ -271,7 +275,8 @@ class MediaPlayerInfo {
        return displayableName;
    }

    void setDisplayableName(String displayableName) {
    void setDisplayableName(@Nullable String displayableName) {
        if (displayableName == null) displayableName = "";
        this.displayableName = displayableName;
    }

@@ -282,6 +287,7 @@ class MediaPlayerInfo {
    void setFeatureBitMask(short[] featureBitMask) {
        synchronized (this) {
            this.featureBitMask = Arrays.copyOf(featureBitMask, featureBitMask.length);
            Arrays.sort(this.featureBitMask);
        }
    }

@@ -295,6 +301,14 @@ class MediaPlayerInfo {
        return false;
    }

    /** Tests if the view of this player presented to the controller is different enough to
     *  justify sending an Available Players Changed update */
    public boolean equalView(MediaPlayerInfo other) {
        return (this.majorType == other.getMajorType()) && (this.subType == other.getSubType())
                && Arrays.equals(this.featureBitMask, other.getFeatureBitMask())
                && this.displayableName.equals(other.getDisplayableName());
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();