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

Commit 3af86fc6 authored by Ajay Panicker's avatar Ajay Panicker
Browse files

Add the MediaPlayerList and fix some checks

The MediaPlayerList class handles keeping track of all the Browsers and
Media Controllers. It will also keep track of which is the active
controller and be able to return the most current metadata.

Fix the metadata equals check as it was comparing more than we wanted.
Depending on where you retrieve the information certain fields may be
filled out differenty even though the song represented was the same.

Also add a queue ID check for the MediaPlayerWrapper in addition to a
null queue.

Bug: 68854188
Test: Compile and Manual testing on full build
Change-Id: I1a25f5a44eb2b5b1775c04baefbfc66c018251e9
parent 58415cd9
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -111,7 +111,8 @@ public class BrowsablePlayerConnector {
                            return;
                        }

                        Log.i(TAG, "Successfully added package to results: " + wrapper.getName());
                        Log.i(TAG, "Successfully added package to results: "
                                + wrapper.getPackageName());
                        mResults.add(wrapper);
                    } break;

@@ -119,7 +120,7 @@ public class BrowsablePlayerConnector {
                        BrowsedPlayerWrapper wrapper = (BrowsedPlayerWrapper) msg.obj;

                        if (msg.arg1 != BrowsedPlayerWrapper.STATUS_SUCCESS) {
                            Log.i(TAG, wrapper.getName() + " is not browsable");
                            Log.i(TAG, wrapper.getPackageName() + " is not browsable");
                            mPendingPlayers.remove(wrapper);
                            return;
                        }
@@ -149,7 +150,7 @@ public class BrowsablePlayerConnector {
                    case MSG_TIMEOUT: {
                        Log.v(TAG, "Timed out waiting for players");
                        for (BrowsedPlayerWrapper wrapper : mPendingPlayers) {
                            if (DEBUG) Log.d(TAG, "Disconnecting " + wrapper.getName());
                            if (DEBUG) Log.d(TAG, "Disconnecting " + wrapper.getPackageName());
                            wrapper.disconnect();
                        }
                        mPendingPlayers.clear();
+16 −24
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.bluetooth.avrcp;

import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.browse.MediaBrowser.MediaItem;
import android.util.Log;

@@ -60,7 +59,7 @@ class BrowsedPlayerWrapper {
    // TODO (apanicke): Store the context in the factories so that we don't need to save this.
    // As long as the service is alive those factories will have a valid context.
    private Context mContext;
    private String mName;
    private String mPackageName;
    private ConnectionCallback mCallback;
    private ConnectionState mConnectionState = ConnectionState.DISCONNECTED;

@@ -97,15 +96,7 @@ class BrowsedPlayerWrapper {
            ConnectionCallback cb) {
        mContext = context;
        mCallback = cb;

        try {
            PackageManager manager = mContext.getPackageManager();
            mName = manager.getApplicationLabel(manager.getApplicationInfo(packageName, 0))
                    .toString();
        } catch (Exception e) {
            Log.w(TAG, "Name Not Found using package name: " + packageName);
            mName = packageName;
        }
        mPackageName = packageName;

        mWrappedBrowser = MediaBrowserFactory.make(
                context,
@@ -127,21 +118,22 @@ class BrowsedPlayerWrapper {

    void connect(ConnectionCallback cb) {
        if (cb == null) {
            Log.wtfStack(TAG, "connect: Trying to connect to " + mName + "with null callback");
            Log.wtfStack(TAG, "connect: Trying to connect to " + mPackageName
                    + "with null callback");
        }
        if (mCallback != null) {
            Log.w(TAG, "connect: Already trying to connect to " + mName);
            Log.w(TAG, "connect: Already trying to connect to " + mPackageName);
            return;
        }

        if (DEBUG) Log.d(TAG, "connect: Connecting to browsable player: " + mName);
        if (DEBUG) Log.d(TAG, "connect: Connecting to browsable player: " + mPackageName);
        mCallback = cb;
        mConnectionState = ConnectionState.CONNECTING;
        mWrappedBrowser.connect();
    }

    void disconnect() {
        if (DEBUG) Log.d(TAG, "disconnect: Disconnecting from " + mName);
        if (DEBUG) Log.d(TAG, "disconnect: Disconnecting from " + mPackageName);
        if (mConnectionState != ConnectionState.DISCONNECTED) {
            // According to the API, as soon as disconnect is sent we shouldn't receive
            // any more callbacks.
@@ -152,8 +144,8 @@ class BrowsedPlayerWrapper {
        mConnectionState = ConnectionState.DISCONNECTED;
    }

    public String getName() {
        return mName;
    public String getPackageName() {
        return mPackageName;
    }

    public String getRootId() {
@@ -168,7 +160,7 @@ class BrowsedPlayerWrapper {
        if (DEBUG) Log.d(TAG, "playItem: Play Item from media ID: " + mediaId);
        if (mConnectionState == ConnectionState.DISCONNECTED) {
            connect((int status, BrowsedPlayerWrapper wrapper) -> {
                if (DEBUG) Log.d(TAG, "playItem: Connected to browsable player " + mName);
                if (DEBUG) Log.d(TAG, "playItem: Connected to browsable player " + mPackageName);

                MediaController controller = MediaControllerFactory.make(mContext,
                        wrapper.mWrappedBrowser.getSessionToken());
@@ -212,7 +204,7 @@ class BrowsedPlayerWrapper {
        // If we are disconnected, connect first then do the lookup
        if (mConnectionState == ConnectionState.DISCONNECTED) {
            connect((int status, BrowsedPlayerWrapper wrapper) -> {
                Log.i(TAG, "getFolderItems: Connected to browsable player: " + mName);
                Log.i(TAG, "getFolderItems: Connected to browsable player: " + mPackageName);
                if (status != STATUS_SUCCESS) {
                    cb.run(status, "", new ArrayList<ListItem>());
                }
@@ -237,7 +229,7 @@ class BrowsedPlayerWrapper {
        @Override
        public void onConnected() {
            mConnectionState = ConnectionState.CONNECTED;
            Log.i(TAG, "onConnected: " + mName + " is connected");
            Log.i(TAG, "onConnected: " + mPackageName + " is connected");
            // Get the root while connected because we may need to use it when disconnected.
            mRoot = mWrappedBrowser.getRoot();
            if (mCallback != null) mCallback.run(STATUS_SUCCESS, BrowsedPlayerWrapper.this);
@@ -248,7 +240,7 @@ class BrowsedPlayerWrapper {
        @Override
        public void onConnectionFailed() {
            mConnectionState = ConnectionState.DISCONNECTED;
            Log.w(TAG, "onConnectionFailed: Connection Failed with " + mName);
            Log.w(TAG, "onConnectionFailed: Connection Failed with " + mPackageName);
            if (mCallback != null) mCallback.run(STATUS_CONN_ERROR, BrowsedPlayerWrapper.this);
            mCallback = null;
        }
@@ -259,7 +251,7 @@ class BrowsedPlayerWrapper {
        public void onConnectionSuspended() {
            mConnectionState = ConnectionState.DISCONNECTED;
            mWrappedBrowser.disconnect();
            Log.i(TAG, "onConnectionSuspended: Connection Suspended with " + mName);
            Log.i(TAG, "onConnectionSuspended: Connection Suspended with " + mPackageName);
        }
    }

@@ -282,7 +274,7 @@ class BrowsedPlayerWrapper {
            }

            if (mCallback == null) {
                Log.w(TAG, "onChildrenLoaded: " + mName
                Log.w(TAG, "onChildrenLoaded: " + mPackageName
                        + " children loaded while callback is null");
            }

@@ -324,7 +316,7 @@ class BrowsedPlayerWrapper {
    }

    public void dump(StringBuilder sb) {
        sb.append("Browsable Package Name: " + mName + "\n");
        sb.append("Browsable Package Name: " + mPackageName + "\n");
        sb.append("   Cached Media ID's: ");
        for (String id : mCachedFolders.keySet()) {
            sb.append(id + " ");
+4 −4
Original line number Diff line number Diff line
@@ -40,10 +40,10 @@ class GPMWrapper extends MediaPlayerWrapper {
            }
        }

        // Check if current playing song in queue matches current Metadata
        if (currItem == null
                || !queueItemToMetadata(currItem).getDescription()
                        .equals(getMetadata().getDescription())) {
        // Check if current playing song in Queue matches current Metadata
        Metadata qitem = Util.toMetadata(currItem);
        Metadata mdata = Util.toMetadata(getMetadata());
        if (currItem == null || !qitem.equals(mdata)) {
            if (DEBUG) {
                Log.d(TAG, "Metadata currently out of sync for Google Play Music");
                Log.d(TAG, "  └ Current queueItem: " + currItem);
+649 −0

File added.

Preview size limit exceeded, changes collapsed.

+4 −43
Original line number Diff line number Diff line
@@ -16,11 +16,9 @@

package com.android.bluetooth.avrcp;

import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -169,7 +167,7 @@ class MediaPlayerWrapper {
     * Return whether the queue, metadata, and queueID are all in sync.
     */
    boolean isMetadataSynced() {
        if (getQueue() != null) {
        if (getQueue() != null && getActiveQueueID() != -1) {
            // Check if currentPlayingQueueId is in the current Queue
            MediaSession.QueueItem currItem = null;

@@ -182,8 +180,9 @@ class MediaPlayerWrapper {
            }

            // Check if current playing song in Queue matches current Metadata
            if (currItem == null
                    || !currItem.getDescription().equals(getMetadata().getDescription())) {
            Metadata qitem = Util.toMetadata(currItem);
            Metadata mdata = Util.toMetadata(getMetadata());
            if (currItem == null || !qitem.equals(mdata)) {
                if (DEBUG) {
                    Log.d(TAG, "Metadata currently out of sync for " + mPackageName);
                    Log.d(TAG, "  └ Current queueItem: " + currItem);
@@ -448,44 +447,6 @@ class MediaPlayerWrapper {
        return false;
    }

    // TODO: Use this function when returning the now playing list
    /**
     * Extracts different pieces of metadata from a MediaSession.QueueItem
     * and builds a MediaMetadata Object out of it.
     */
    MediaMetadata queueItemToMetadata(MediaSession.QueueItem item) {
        final String[] metadataStringKeys = {
                MediaMetadata.METADATA_KEY_TITLE,
                MediaMetadata.METADATA_KEY_ARTIST,
                MediaMetadata.METADATA_KEY_ALBUM,
                MediaMetadata.METADATA_KEY_GENRE };

        MediaMetadata.Builder newMetadata = new MediaMetadata.Builder();
        MediaDescription description = item.getDescription();
        Bundle extras = description.getExtras();

        for (String key : metadataStringKeys) {
            String value = extras.getString(key);

            if (key == MediaMetadata.METADATA_KEY_TITLE && value == null) {
                value = description.getTitle().toString();
            }

            if (value == null) {
                if (DEBUG) {
                    Log.d(TAG, "queueItemToMetadata: " + description + " is missing key: " + key);
                }
                continue;
            }
            newMetadata.putString(key, value);
        }

        long duration = extras.getLong(MediaMetadata.METADATA_KEY_DURATION);
        newMetadata.putLong(MediaMetadata.METADATA_KEY_DURATION, duration);

        return newMetadata.build();
    }

    private static void e(String message) {
        if (sTesting) {
            Log.wtfStack(TAG, message);
Loading