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

Commit 86142da1 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

Improve RemoteControlDisplay registration

When a new RemoteControlDisplay gets registered, don't cause all
  existing RemoteControlDisplays to re-receive RemoteControl
  information they already have.

Bug 8417073

Change-Id: Icc8e7104d6870f748fddd702692789dbaef948ac
parent 33ed738d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -40,6 +40,13 @@ oneway interface IRemoteControlClient
     */
    void onInformationRequested(int generationId, int infoFlags);

    /**
     * Notifies a remote control client that information for the given generation ID is
     * requested for the given IRemoteControlDisplay alone.
     * @param rcd the display to which current info should be sent
     */
    void informationRequestForDisplay(IRemoteControlDisplay rcd, int w, int h);

    /**
     * Sets the generation counter of the current client that is displayed on the remote control.
     */
+50 −2
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ public class MediaFocusControl implements OnFinished {
    private static final int MSG_RCC_NEW_PLAYBACK_STATE = 7;
    private static final int MSG_RCC_SEEK_REQUEST = 8;
    private static final int MSG_RCC_UPDATE_METADATA = 9;
    private static final int MSG_RCDISPLAY_INIT_INFO = 10;

    // sendMsg() flags
    /** If the msg is already queued, replace it with this one. */
@@ -214,6 +215,12 @@ public class MediaFocusControl implements OnFinished {
                case MSG_PROMOTE_RCC:
                    onPromoteRcc(msg.arg1);
                    break;

                case MSG_RCDISPLAY_INIT_INFO:
                    // msg.obj is guaranteed to be non null
                    onRcDisplayInitInfo((IRemoteControlDisplay)msg.obj /*newRcd*/,
                            msg.arg1/*w*/, msg.arg2/*h*/);
                    break;
            }
        }
    }
@@ -852,6 +859,11 @@ public class MediaFocusControl implements OnFinished {
     * Access protected by mCurrentRcLock.
     */
    private IRemoteControlClient mCurrentRcClient = null;
    /**
     * The PendingIntent associated with mCurrentRcClient. Its value is irrelevant
     * if mCurrentRcClient is null
     */
    private PendingIntent mCurrentRcClientIntent = null;

    private final static int RC_INFO_NONE = 0;
    private final static int RC_INFO_ALL =
@@ -1446,6 +1458,7 @@ public class MediaFocusControl implements OnFinished {

                    // tell the current client that it needs to send info
                    try {
                        //TODO change name to informationRequestForAllDisplays()
                        mCurrentRcClient.onInformationRequested(mCurrentRcClientGen, flags);
                    } catch (RemoteException e) {
                        Log.e(TAG, "Current valid remote client is dead: "+e);
@@ -1460,6 +1473,36 @@ public class MediaFocusControl implements OnFinished {
        }
    }

    /**
     * Called when processing MSG_RCDISPLAY_INIT_INFO event
     * Causes the current RemoteControlClient to send its info (metadata, playstate...) to
     *   a single RemoteControlDisplay, NOT all of them, as with MSG_RCDISPLAY_UPDATE.
     */
    private void onRcDisplayInitInfo(IRemoteControlDisplay newRcd, int w, int h) {
        synchronized(mRCStack) {
            synchronized(mCurrentRcLock) {
                if (mCurrentRcClient != null) {
                    if (DEBUG_RC) { Log.i(TAG, "Init RCD with current info"); }
                    try {
                        // synchronously update the new RCD with the current client generation
                        // and matching PendingIntent
                        newRcd.setCurrentClientId(mCurrentRcClientGen, mCurrentRcClientIntent,
                                false);

                        // tell the current RCC that it needs to send info, but only to the new RCD
                        try {
                            mCurrentRcClient.informationRequestForDisplay(newRcd, w, h);
                        } catch (RemoteException e) {
                            Log.e(TAG, "Current valid remote client is dead: ", e);
                            mCurrentRcClient = null;
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "Dead display in onRcDisplayInitInfo()", e);
                    }
                }
            }
        }
    }

    /**
     * Helper function:
@@ -1497,6 +1540,7 @@ public class MediaFocusControl implements OnFinished {
                infoFlagsAboutToBeUsed = RC_INFO_ALL;
            }
            mCurrentRcClient = rcse.mRcClient;
            mCurrentRcClientIntent = rcse.mMediaIntent;
        }
        // will cause onRcDisplayUpdate() to be called in AudioService's handler thread
        mEventHandler.sendMessage( mEventHandler.obtainMessage(MSG_RCDISPLAY_UPDATE,
@@ -1923,8 +1967,12 @@ public class MediaFocusControl implements OnFinished {
                    }
                }

                // we have a new display, of which all the clients are now aware: have it be updated
                checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
                // we have a new display, of which all the clients are now aware: have it be
                // initialized wih the current gen ID and the current client info, do not
                // reset the information for the other (existing) displays
                sendMsg(mEventHandler, MSG_RCDISPLAY_INIT_INFO, SENDMSG_QUEUE,
                        w /*arg1*/, h /*arg2*/,
                        rcd /*obj*/, 0/*delay*/);
            }
        }
    }
+98 −20
Original line number Diff line number Diff line
@@ -515,13 +515,13 @@ public class RemoteControlClient
                mEditorArtwork = null;
                if (mMetadataChanged & mArtworkChanged) {
                    // send to remote control display if conditions are met
                    sendMetadataWithArtwork_syncCacheLock();
                    sendMetadataWithArtwork_syncCacheLock(null, 0, 0);
                } else if (mMetadataChanged) {
                    // send to remote control display if conditions are met
                    sendMetadata_syncCacheLock();
                    sendMetadata_syncCacheLock(null);
                } else if (mArtworkChanged) {
                    // send to remote control display if conditions are met
                    sendArtwork_syncCacheLock();
                    sendArtwork_syncCacheLock(null, 0, 0);
                }
                mApplied = true;
            }
@@ -620,7 +620,7 @@ public class RemoteControlClient
                mPlaybackStateChangeTimeMs = SystemClock.elapsedRealtime();

                // send to remote control display if conditions are met
                sendPlaybackState_syncCacheLock();
                sendPlaybackState_syncCacheLock(null);
                // update AudioService
                sendAudioServiceNewPlaybackState_syncCacheLock();

@@ -705,7 +705,7 @@ public class RemoteControlClient
            mTransportControlFlags = transportControlFlags;

            // send to remote control display if conditions are met
            sendTransportControlInfo_syncCacheLock();
            sendTransportControlInfo_syncCacheLock(null);
        }
    }

@@ -791,7 +791,7 @@ public class RemoteControlClient
            mPositionUpdateListener = l;
            if (oldCapa != mPlaybackPositionCapabilities) {
                // tell RCDs that this RCC's playback position capabilities have changed
                sendTransportControlInfo_syncCacheLock();
                sendTransportControlInfo_syncCacheLock(null);
            }
        }
    }
@@ -813,7 +813,7 @@ public class RemoteControlClient
            mPositionProvider = l;
            if (oldCapa != mPlaybackPositionCapabilities) {
                // tell RCDs that this RCC's playback position capabilities have changed
                sendTransportControlInfo_syncCacheLock();
                sendTransportControlInfo_syncCacheLock(null);
            }
            if ((mPositionProvider != null) && (mEventHandler != null)
                    && playbackPositionShouldMove(mPlaybackState)) {
@@ -1083,6 +1083,7 @@ public class RemoteControlClient
     */
    private final IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() {

        //TODO change name to informationRequestForAllDisplays()
        public void onInformationRequested(int generationId, int infoFlags) {
            // only post messages, we can't block here
            if (mEventHandler != null) {
@@ -1096,12 +1097,30 @@ public class RemoteControlClient
                mEventHandler.removeMessages(MSG_REQUEST_METADATA);
                mEventHandler.removeMessages(MSG_REQUEST_TRANSPORTCONTROL);
                mEventHandler.removeMessages(MSG_REQUEST_ARTWORK);
                mEventHandler.removeMessages(MSG_REQUEST_METADATA_ARTWORK);
                mEventHandler.sendMessage(
                        mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE));
                        mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE, null));
                mEventHandler.sendMessage(
                        mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL));
                mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_METADATA));
                mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_ARTWORK));
                        mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL, null));
                mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_METADATA_ARTWORK,
                        0, 0, null));
            }
        }

        public void informationRequestForDisplay(IRemoteControlDisplay rcd, int w, int h) {
            // only post messages, we can't block here
            if (mEventHandler != null) {
                mEventHandler.sendMessage(
                        mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL, rcd));
                mEventHandler.sendMessage(
                        mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE, rcd));
                if ((w > 0) && (h > 0)) {
                    mEventHandler.sendMessage(
                            mEventHandler.obtainMessage(MSG_REQUEST_METADATA_ARTWORK, w, h, rcd));
                } else {
                    mEventHandler.sendMessage(
                            mEventHandler.obtainMessage(MSG_REQUEST_METADATA, rcd));
                }
            }
        }

@@ -1207,6 +1226,7 @@ public class RemoteControlClient
    private final static int MSG_POSITION_DRIFT_CHECK = 11;
    private final static int MSG_DISPLAY_WANTS_POS_SYNC = 12;
    private final static int MSG_UPDATE_METADATA = 13;
    private final static int MSG_REQUEST_METADATA_ARTWORK = 14;

    private class EventHandler extends Handler {
        public EventHandler(RemoteControlClient rcc, Looper looper) {
@@ -1218,22 +1238,29 @@ public class RemoteControlClient
            switch(msg.what) {
                case MSG_REQUEST_PLAYBACK_STATE:
                    synchronized (mCacheLock) {
                        sendPlaybackState_syncCacheLock();
                        sendPlaybackState_syncCacheLock((IRemoteControlDisplay)msg.obj);
                    }
                    break;
                case MSG_REQUEST_METADATA:
                    synchronized (mCacheLock) {
                        sendMetadata_syncCacheLock();
                        sendMetadata_syncCacheLock((IRemoteControlDisplay)msg.obj);
                    }
                    break;
                case MSG_REQUEST_TRANSPORTCONTROL:
                    synchronized (mCacheLock) {
                        sendTransportControlInfo_syncCacheLock();
                        sendTransportControlInfo_syncCacheLock((IRemoteControlDisplay)msg.obj);
                    }
                    break;
                case MSG_REQUEST_ARTWORK:
                    synchronized (mCacheLock) {
                        sendArtwork_syncCacheLock();
                        sendArtwork_syncCacheLock((IRemoteControlDisplay)msg.obj,
                                msg.arg1, msg.arg2);
                    }
                    break;
                case MSG_REQUEST_METADATA_ARTWORK:
                    synchronized (mCacheLock) {
                        sendMetadataWithArtwork_syncCacheLock((IRemoteControlDisplay)msg.obj,
                                msg.arg1, msg.arg2);
                    }
                    break;
                case MSG_NEW_INTERNAL_CLIENT_GEN:
@@ -1272,8 +1299,19 @@ public class RemoteControlClient
    //===========================================================
    // Communication with the IRemoteControlDisplay (the displays known to the system)

    private void sendPlaybackState_syncCacheLock() {
    private void sendPlaybackState_syncCacheLock(IRemoteControlDisplay target) {
        if (mCurrentClientGenId == mInternalClientGenId) {
            if (target != null) {
                try {
                    target.setPlaybackState(mInternalClientGenId,
                            mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs,
                            mPlaybackSpeed);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error in setPlaybackState() for dead display " + target, e);
                }
                return;
            }
            // target == null implies all displays must be updated
            final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
            while (displayIterator.hasNext()) {
                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
@@ -1289,8 +1327,17 @@ public class RemoteControlClient
        }
    }

    private void sendMetadata_syncCacheLock() {
    private void sendMetadata_syncCacheLock(IRemoteControlDisplay target) {
        if (mCurrentClientGenId == mInternalClientGenId) {
            if (target != null) {
                try {
                    target.setMetadata(mInternalClientGenId, mMetadata);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error in setMetadata() for dead display " + target, e);
                }
                return;
            }
            // target == null implies all displays must be updated
            final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
            while (displayIterator.hasNext()) {
                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
@@ -1304,8 +1351,19 @@ public class RemoteControlClient
        }
    }

    private void sendTransportControlInfo_syncCacheLock() {
    private void sendTransportControlInfo_syncCacheLock(IRemoteControlDisplay target) {
        if (mCurrentClientGenId == mInternalClientGenId) {
            if (target != null) {
                try {
                    target.setTransportControlInfo(mInternalClientGenId,
                            mTransportControlFlags, mPlaybackPositionCapabilities);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error in setTransportControlFlags() for dead display " + target,
                            e);
                }
                return;
            }
            // target == null implies all displays must be updated
            final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
            while (displayIterator.hasNext()) {
                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
@@ -1321,9 +1379,15 @@ public class RemoteControlClient
        }
    }

    private void sendArtwork_syncCacheLock() {
    private void sendArtwork_syncCacheLock(IRemoteControlDisplay target, int w, int h) {
        // FIXME modify to cache all requested sizes?
        if (mCurrentClientGenId == mInternalClientGenId) {
            if (target != null) {
                final DisplayInfoForClient di = new DisplayInfoForClient(target, w, h);
                sendArtworkToDisplay(di);
                return;
            }
            // target == null implies all displays must be updated
            final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
            while (displayIterator.hasNext()) {
                if (!sendArtworkToDisplay((DisplayInfoForClient) displayIterator.next())) {
@@ -1353,9 +1417,23 @@ public class RemoteControlClient
        return true;
    }

    private void sendMetadataWithArtwork_syncCacheLock() {
    private void sendMetadataWithArtwork_syncCacheLock(IRemoteControlDisplay target, int w, int h) {
        // FIXME modify to cache all requested sizes?
        if (mCurrentClientGenId == mInternalClientGenId) {
            if (target != null) {
                try {
                    if ((w > 0) && (h > 0)) {
                        Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, w, h);
                        target.setAllMetadata(mInternalClientGenId, mMetadata, artwork);
                    } else {
                        target.setMetadata(mInternalClientGenId, mMetadata);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "Error in set(All)Metadata() for dead display " + target, e);
                }
                return;
            }
            // target == null implies all displays must be updated
            final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
            while (displayIterator.hasNext()) {
                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();