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

Commit 4426e42a authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

Bug 5045498 New implementation of remote control API

Remote control displays expose an IRemoteControlDisplay interface
 which they register through AudioManager.
Remote control clients create a RemoteControlClient object, which
 implicitely exposes an IRemoteControlClient interface registered
 in AudioService through AudioManager.
AudioService tells all clients and displays when a new client
 is the one that should be displayed.
A client's data gets sent to the display when it is valid, or
 it sets new data (while being valid).

The implementation for setting metadata and album art is temporary,
 and will migrate to the MetadataEditor API in future CLs.

Change-Id: Ibab6ea1d94c68f32482c760c6ae269541f885548
parent 0197d825
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -183,7 +183,8 @@ LOCAL_SRC_FILES += \
	media/java/android/media/IAudioFocusDispatcher.aidl \
	media/java/android/media/IMediaScannerListener.aidl \
	media/java/android/media/IMediaScannerService.aidl \
	media/java/android/media/IRemoteControlClientDispatcher.aidl \
	media/java/android/media/IRemoteControlClient.aidl \
	media/java/android/media/IRemoteControlDisplay.aidl \
	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
	telephony/java/com/android/internal/telephony/ITelephony.aidl \
+1 −0
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/SystemUI_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/R/com/android/systemui/R.java)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
+19 −149
Original line number Diff line number Diff line
@@ -1715,161 +1715,54 @@ public class AudioManager {
        }
    }

    /**
     * Acts as a proxy between AudioService and the RemoteControlClient
     */
    private IRemoteControlClientDispatcher mRcClientDispatcher =
            new IRemoteControlClientDispatcher.Stub() {

        public String getMetadataStringForClient(String clientName, int field) {
            RemoteControlClient realClient;
            synchronized(mRcClientMap) {
                realClient = mRcClientMap.get(clientName);
            }
            if (realClient != null) {
                return realClient.getMetadataString(field);
            } else {
                return null;
            }
        }

        public int getPlaybackStateForClient(String clientName) {
            RemoteControlClient realClient;
            synchronized(mRcClientMap) {
                realClient = mRcClientMap.get(clientName);
            }
            if (realClient != null) {
                return realClient.getPlaybackState();
            } else {
                return 0;
            }
        }

        public int getTransportControlFlagsForClient(String clientName) {
            RemoteControlClient realClient;
            synchronized(mRcClientMap) {
                realClient = mRcClientMap.get(clientName);
            }
            if (realClient != null) {
                return realClient.getTransportControlFlags();
            } else {
                return 0;
            }
        }

        public Bitmap getAlbumArtForClient(String clientName, int maxWidth, int maxHeight) {
            RemoteControlClient realClient;
            synchronized(mRcClientMap) {
                realClient = mRcClientMap.get(clientName);
            }
            if (realClient != null) {
                return realClient.getAlbumArt(maxWidth, maxHeight);
            } else {
                return null;
            }
        }
    };

    private HashMap<String, RemoteControlClient> mRcClientMap =
            new HashMap<String, RemoteControlClient>();

    private String getIdForRcClient(RemoteControlClient client) {
        // client is guaranteed to be non-null
        return client.toString();
    }

    /**
     * @hide
     * CANDIDATE FOR SDK
     * Registers the remote control client for providing information to display on the remote
     * controls.
     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
     *      that will receive the media button intent, and associated with the remote control
     *      client. This method has no effect if
     *      {@link #registerMediaButtonEventReceiver(ComponentName)} hasn't been called
     *      with the same eventReceiver, or if
     *      {@link #unregisterMediaButtonEventReceiver(ComponentName)} has been called.
     * @param rcClient the remote control client associated with the event receiver, responsible
     * @param rcClient the remote control client associated responsible
     *      for providing the information to display on the remote control.
     */
    public void registerRemoteControlClient(ComponentName eventReceiver,
            RemoteControlClient rcClient) {
        if ((eventReceiver == null) || (rcClient == null)) {
            return;
        }
        String clientKey = getIdForRcClient(rcClient);
        synchronized(mRcClientMap) {
            if (mRcClientMap.containsKey(clientKey)) {
    public void registerRemoteControlClient(RemoteControlClient rcClient) {
        if ((rcClient == null) || (rcClient.getRcEventReceiver() == null)) {
            return;
        }
            mRcClientMap.put(clientKey, rcClient);
        }
        IAudioService service = getService();
        try {
            service.registerRemoteControlClient(eventReceiver, mRcClientDispatcher, clientKey,
            service.registerRemoteControlClient(rcClient.getRcEventReceiver(), /* eventReceiver */
                    rcClient.getIRemoteControlClient(),                        /* rcClient      */
                    rcClient.toString(),                                       /* clientName    */
                    // used to match media button event receiver and audio focus
                    mContext.getPackageName());
                    mContext.getPackageName());                                /* packageName   */
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in registerRemoteControlClient"+e);
            synchronized(mRcClientMap) {
                mRcClientMap.remove(clientKey);
            }
        }
    }

    /**
     * @hide
     * CANDIDATE FOR SDK
     * Unregisters the remote control client that was providing information to display on the
     * remotes.
     * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
     *      that receives the media button intent, and associated with the remote control
     *      client.
     * @param rcClient the remote control client to unregister
     * @see #registerRemoteControlClient(ComponentName, RemoteControlClient)
     * @see #registerRemoteControlClient(RemoteControlClient)
     */
    public void unregisterRemoteControlClient(ComponentName eventReceiver,
            RemoteControlClient rcClient) {
        if ((eventReceiver == null) || (rcClient == null)) {
    public void unregisterRemoteControlClient(RemoteControlClient rcClient) {
        if ((rcClient == null) || (rcClient.getRcEventReceiver() == null)) {
            return;
        }
        IAudioService service = getService();
        try {
            // remove locally
            boolean unregister = true;
            synchronized(mRcClientMap) {
                if (mRcClientMap.remove(getIdForRcClient(rcClient)) == null) {
                    unregister = false;
                }
            }
            if (unregister) {
                // unregistering a RemoteControlClient is equivalent to setting it to null
                service.registerRemoteControlClient(eventReceiver, null, null,
                        mContext.getPackageName());
            }
            service.unregisterRemoteControlClient(rcClient.getRcEventReceiver(), /* eventReceiver */
                    rcClient.getIRemoteControlClient());                         /* rcClient      */
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);
        }
    }

    /**
     * @hide
     * Returns the current remote control client.
     * @param rcClientId the generation counter that matches the extra
     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT_GENERATION} in the
     *     {@link AudioManager#REMOTE_CONTROL_CLIENT_CHANGED} event
     * @return the current RemoteControlClient from which information to display on the remote
     *     control can be retrieved, or null if rcClientId doesn't match the current generation
     *     counter.
     */
    public IRemoteControlClientDispatcher getRemoteControlClientDispatcher(int rcClientId) {
        IAudioService service = getService();
        try {
            return service.getRemoteControlClientDispatcher(rcClientId);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in getRemoteControlClient "+e);
            return null;
        }
    }

    // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
    /**
     * @hide
     * Broadcast intent action indicating that the displays on the remote controls
@@ -1882,6 +1775,7 @@ public class AudioManager {
    public static final String REMOTE_CONTROL_CLIENT_CHANGED =
            "android.media.REMOTE_CONTROL_CLIENT_CHANGED";

    // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
    /**
     * @hide
     * The IRemoteControlClientDispatcher monotonically increasing generation counter.
@@ -1891,6 +1785,7 @@ public class AudioManager {
    public static final String EXTRA_REMOTE_CONTROL_CLIENT_GENERATION =
            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION";

    // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
    /**
     * @hide
     * The name of the RemoteControlClient.
@@ -1902,6 +1797,7 @@ public class AudioManager {
    public static final String EXTRA_REMOTE_CONTROL_CLIENT_NAME =
            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_NAME";

    // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
    /**
     * @hide
     * The media button event receiver associated with the RemoteControlClient.
@@ -1913,6 +1809,7 @@ public class AudioManager {
    public static final String EXTRA_REMOTE_CONTROL_EVENT_RECEIVER =
            "android.media.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER";

    // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
    /**
     * @hide
     * The flags describing what information has changed in the current remote control client.
@@ -1922,33 +1819,6 @@ public class AudioManager {
    public static final String EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED =
            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED";

    /**
     * @hide
     * Notifies the users of the associated remote control client that the information to display
     * has changed.
     @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
     *      that will receive the media button intent, and associated with the remote control
     *      client. This method has no effect if
     *      {@link #registerMediaButtonEventReceiver(ComponentName)} hasn't been called
     *      with the same eventReceiver, or if
     *      {@link #unregisterMediaButtonEventReceiver(ComponentName)} has been called.
     * @param infoFlag the type of information that has changed since this method was last called,
     *      or the event receiver was registered. Use one or multiple of the following flags to
     *      describe what changed:
     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_METADATA},
     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_KEY_MEDIA},
     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_PLAYSTATE},
     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_ALBUM_ART}.
     */
    public void notifyRemoteControlInformationChanged(ComponentName eventReceiver, int infoFlag) {
        IAudioService service = getService();
        try {
            service.notifyRemoteControlInformationChanged(eventReceiver, infoFlag);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in refreshRemoteControlDisplay"+e);
        }
    }

    /**
     *  @hide
     *  Reload audio settings. This method is called by Settings backup
+227 −70

File changed.

Preview size limit exceeded, changes collapsed.

+9 −7
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ package android.media;

import android.content.ComponentName;
import android.media.IAudioFocusDispatcher;
import android.media.IRemoteControlClientDispatcher;
import android.media.IRemoteControlClient;
import android.media.IRemoteControlDisplay;

/**
 * {@hide}
@@ -88,13 +89,14 @@ interface IAudioService {

    void unregisterMediaButtonEventReceiver(in ComponentName eventReceiver);

    void registerRemoteControlClient(in ComponentName eventReceiver,
           in IRemoteControlClientDispatcher rcClient, in String clientName,
           in String callingPackageName);
    oneway void registerRemoteControlClient(in ComponentName eventReceiver,
           in IRemoteControlClient rcClient, in String clientName, in String callingPackageName);
    oneway void unregisterRemoteControlClient(in ComponentName eventReceiver,
           in IRemoteControlClient rcClient);

    IRemoteControlClientDispatcher getRemoteControlClientDispatcher(in int rcClientId);

    void notifyRemoteControlInformationChanged(in ComponentName eventReceiver, int infoFlag);
    oneway void   registerRemoteControlDisplay(in IRemoteControlDisplay rcd);
    oneway void unregisterRemoteControlDisplay(in IRemoteControlDisplay rcd);
    oneway void remoteControlDisplayUsesBitmapSize(in IRemoteControlDisplay rcd, int w, int h);

    void startBluetoothSco(IBinder cb);

Loading