Merge "Remote volume handling in MediaRouter" into jb-dev
diff --git a/Android.mk b/Android.mk
index 5aaea97..79e3140 100644
--- a/Android.mk
+++ b/Android.mk
@@ -193,11 +193,12 @@
 	location/java/android/location/INetInitiatedListener.aidl \
 	media/java/android/media/IAudioService.aidl \
 	media/java/android/media/IAudioFocusDispatcher.aidl \
-    media/java/android/media/IAudioRoutesObserver.aidl \
+	media/java/android/media/IAudioRoutesObserver.aidl \
 	media/java/android/media/IMediaScannerListener.aidl \
 	media/java/android/media/IMediaScannerService.aidl \
 	media/java/android/media/IRemoteControlClient.aidl \
 	media/java/android/media/IRemoteControlDisplay.aidl \
+	media/java/android/media/IRemoteVolumeObserver.aidl \
 	media/java/android/media/IRingtonePlayer.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 50972e8..76dfac4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2153,19 +2153,6 @@
             "android.intent.action.USB_AUDIO_DEVICE_PLUG";
 
     /**
-     * @hide (to be un-hidden)
-     * Broadcast Action: the volume handled by the receiver should be updated based on the
-     * mutually exclusive extras, {@link #EXTRA_VOLUME_UPDATE_DIRECTION}
-     * and {@link #EXTRA_VOLUME_UPDATE_VALUE}.
-     *
-     * @see #EXTRA_VOLUME_UPDATE_DIRECTION
-     * @see #EXTRA_VOLUME_UPDATE_VALUE
-     * @see android.media.RemoteControlClient
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_VOLUME_UPDATE = "android.intent.action.VOLUME_UPDATE";
-
-    /**
      * <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p>
      * <ul>
      *   <li><em>state</em> - A boolean value indicating whether the settings is on or off.</li>
@@ -2854,26 +2841,6 @@
     public static final String EXTRA_USERID =
             "android.intent.extra.user_id";
 
-    /**
-     * @hide (to be un-hidden)
-     * An integer indicating whether the volume is to be increased (positive value) or decreased
-     * (negative value). For bundled changes, the absolute value indicates the number of changes
-     * in the same direction, e.g. +3 corresponds to three "volume up" changes.
-     * @see #ACTION_VOLUME_UPDATE
-     */
-    public static final String EXTRA_VOLUME_UPDATE_DIRECTION =
-            "android.intent.extra.VOLUME_UPDATE_DIRECTION";
-
-    /**
-     * @hide (to be un-hidden)
-     * An integer indicating the new volume value, always between 0 and the value set for
-     * {@link RemoteControlClient#PLAYBACKINFO_VOLUME_MAX} with
-     * {@link RemoteControlClient#setPlaybackInformation(int, int)}
-     * @see #ACTION_VOLUME_UPDATE
-     */
-    public static final String EXTRA_VOLUME_UPDATE_VALUE =
-            "android.intent.extra.VOLUME_UPDATE_VALUE";
-
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 418dc52..1b476027 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -4243,6 +4243,7 @@
         public int mPlaybackVolumeHandling;
         public int mPlaybackStream;
         public int mPlaybackState;
+        public IRemoteVolumeObserver mRemoteVolumeObs;
 
         public void resetPlaybackInfo() {
             mPlaybackType = RemoteControlClient.PLAYBACK_TYPE_LOCAL;
@@ -4251,6 +4252,7 @@
             mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
             mPlaybackStream = AudioManager.STREAM_MUSIC;
             mPlaybackState = RemoteControlClient.PLAYSTATE_STOPPED;
+            mRemoteVolumeObs = null;
         }
 
         /** precondition: mediaIntent != null, eventReceiver != null */
@@ -4335,7 +4337,9 @@
                         "  -- state: " + rcse.mPlaybackState +
                         "  -- vol handling: " + rcse.mPlaybackVolumeHandling +
                         "  -- vol: " + rcse.mPlaybackVolume +
-                        "  -- volMax: " + rcse.mPlaybackVolumeMax);
+                        "  -- volMax: " + rcse.mPlaybackVolumeMax +
+                        "  -- volObs: " + rcse.mRemoteVolumeObs);
+                
             }
         }
         synchronized (mMainRemote) {
@@ -5018,6 +5022,20 @@
         }
     }
 
+    // FIXME send a message instead of updating the stack synchronously
+    public void registerRemoteVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
+        synchronized(mRCStack) {
+            Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+            while(stackIterator.hasNext()) {
+                RemoteControlStackEntry rcse = stackIterator.next();
+                if (rcse.mRccId == rccId) {
+                    rcse.mRemoteVolumeObs = rvo;
+                    break;
+                }
+            }
+        }
+    }
+
     /**
      * Checks if a remote client is active on the supplied stream type. Update the remote stream
      * volume state if found and playing
@@ -5100,23 +5118,24 @@
             // only handling discrete events
             return;
         }
-        String packageForRcc = null;
+        IRemoteVolumeObserver rvo = null;
         synchronized (mRCStack) {
             Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
             while(stackIterator.hasNext()) {
                 RemoteControlStackEntry rcse = stackIterator.next();
                 //FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
                 if (rcse.mRccId == rccId) {
-                    packageForRcc = rcse.mReceiverComponent.getPackageName();
+                    rvo = rcse.mRemoteVolumeObs;
                     break;
                 }
             }
         }
-        if (packageForRcc != null) {
-            Intent intent = new Intent(Intent.ACTION_VOLUME_UPDATE);
-            intent.putExtra(Intent.EXTRA_VOLUME_UPDATE_DIRECTION, direction);
-            intent.setPackage(packageForRcc);
-            mContext.sendBroadcast(intent);
+        if (rvo != null) {
+            try {
+                rvo.dispatchRemoteVolumeUpdate(direction, -1);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error dispatching relative volume update", e);
+            }
         }
     }
 
@@ -5147,23 +5166,24 @@
             }
             rccId = mMainRemote.mRccId;
         }
-        String packageForRcc = null;
+        IRemoteVolumeObserver rvo = null;
         synchronized (mRCStack) {
             Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
             while(stackIterator.hasNext()) {
                 RemoteControlStackEntry rcse = stackIterator.next();
                 if (rcse.mRccId == rccId) {
                     //FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
-                    packageForRcc = rcse.mReceiverComponent.getPackageName();
+                    rvo = rcse.mRemoteVolumeObs;
                     break;
                 }
             }
         }
-        if (packageForRcc != null) {
-            Intent intent = new Intent(Intent.ACTION_VOLUME_UPDATE);
-            intent.putExtra(Intent.EXTRA_VOLUME_UPDATE_VALUE, vol);
-            intent.setPackage(packageForRcc);
-            mContext.sendBroadcast(intent);
+        if (rvo != null) {
+            try {
+                rvo.dispatchRemoteVolumeUpdate(0, vol);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error dispatching absolute volume update", e);
+            }
         }
     }
 
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 83483c6..854eb3f 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -24,6 +24,7 @@
 import android.media.IAudioRoutesObserver;
 import android.media.IRemoteControlClient;
 import android.media.IRemoteControlDisplay;
+import android.media.IRemoteVolumeObserver;
 import android.media.IRingtonePlayer;
 import android.net.Uri;
 import android.view.KeyEvent;
@@ -135,6 +136,7 @@
     oneway void setPlaybackInfoForRcc(int rccId, int what, int value);
            int  getRemoteStreamMaxVolume();
            int  getRemoteStreamVolume();
+    oneway void registerRemoteVolumeObserverForRcc(int rccId, in IRemoteVolumeObserver rvo);
 
     void startBluetoothSco(IBinder cb);
     void stopBluetoothSco(IBinder cb);
diff --git a/media/java/android/media/IRemoteVolumeObserver.aidl b/media/java/android/media/IRemoteVolumeObserver.aidl
new file mode 100644
index 0000000..7ff0c06
--- /dev/null
+++ b/media/java/android/media/IRemoteVolumeObserver.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+
+/**
+ * AIDL for the AudioService to report requests for remote volume update requests.
+ * @hide
+ */
+oneway interface IRemoteVolumeObserver {
+    void dispatchRemoteVolumeUpdate(int direction, int value);
+}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index a9e6e3d..a309c3f 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -589,9 +589,46 @@
         RouteGroup mGroup;
         final RouteCategory mCategory;
         Drawable mIcon;
+        // playback information
+        int mPlaybackType = PLAYBACK_TYPE_LOCAL;
+        int mVolumeMax = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
+        int mVolume = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
+        int mVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
+        int mPlaybackStream = AudioManager.STREAM_MUSIC;
+        VolumeCallbackInfo mVcb;
 
         private Object mTag;
 
+        /**
+         * @hide (to be un-hidden)
+         * The default playback type, "local", indicating the presentation of the media is happening
+         * on the same device (e.g. a phone, a tablet) as where it is controlled from.
+         * @see #setPlaybackType(int)
+         */
+        public final static int PLAYBACK_TYPE_LOCAL = 0;
+        /**
+         * @hide (to be un-hidden)
+         * A playback type indicating the presentation of the media is happening on
+         * a different device (i.e. the remote device) than where it is controlled from.
+         * @see #setPlaybackType(int)
+         */
+        public final static int PLAYBACK_TYPE_REMOTE = 1;
+        /**
+         * @hide (to be un-hidden)
+         * Playback information indicating the playback volume is fixed, i.e. it cannot be
+         * controlled from this object. An example of fixed playback volume is a remote player,
+         * playing over HDMI where the user prefers to control the volume on the HDMI sink, rather
+         * than attenuate at the source.
+         * @see #setVolumeHandling(int)
+         */
+        public final static int PLAYBACK_VOLUME_FIXED = 0;
+        /**
+         * @hide (to be un-hidden)
+         * Playback information indicating the playback volume is variable and can be controlled
+         * from this object.
+         */
+        public final static int PLAYBACK_VOLUME_VARIABLE = 1;
+
         RouteInfo(RouteCategory category) {
             mCategory = category;
         }
@@ -685,6 +722,71 @@
             return mTag;
         }
 
+        /**
+         * @hide (to be un-hidden)
+         * @return the type of playback associated with this route
+         * @see UserRouteInfo#setPlaybackType(int)
+         */
+        public int getPlaybackType() {
+            return mPlaybackType;
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * @return the stream over which the playback associated with this route is performed
+         * @see UserRouteInfo#setPlaybackStream(int)
+         */
+        public int getPlaybackStream() {
+            return mPlaybackStream;
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * @return the volume at which the playback associated with this route is performed
+         * @see UserRouteInfo#setVolume(int)
+         */
+        public int getVolume() {
+            if (mPlaybackType == PLAYBACK_TYPE_LOCAL) {
+                int vol = 0;
+                try {
+                    vol = sStatic.mAudioService.getStreamVolume(mPlaybackStream);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error getting local stream volume", e);
+                }
+                return vol;
+            } else {
+                return mVolume;
+            }
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * @return the maximum volume at which the playback associated with this route is performed
+         * @see UserRouteInfo#setVolumeMax(int)
+         */
+        public int getVolumeMax() {
+            if (mPlaybackType == PLAYBACK_TYPE_LOCAL) {
+                int volMax = 0;
+                try {
+                    volMax = sStatic.mAudioService.getStreamMaxVolume(mPlaybackStream);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error getting local stream volume", e);
+                }
+                return volMax;
+            } else {
+                return mVolumeMax;
+            }
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * @return how volume is handling on the route
+         * @see UserRouteInfo#setVolumeHandling(int)
+         */
+        public int getVolumeHandling() {
+            return mVolumeHandling;
+        }
+
         void setStatusInt(CharSequence status) {
             if (!status.equals(mStatus)) {
                 mStatus = status;
@@ -695,6 +797,24 @@
             }
         }
 
+        final IRemoteVolumeObserver.Stub mRemoteVolObserver = new IRemoteVolumeObserver.Stub() {
+            public void dispatchRemoteVolumeUpdate(final int direction, final int value) {
+                sStatic.mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                      //Log.d(TAG, "dispatchRemoteVolumeUpdate dir=" + direction + " val=" + value);
+                        if (mVcb != null) {
+                            if (direction != 0) {
+                                mVcb.vcb.onVolumeUpdateRequest(mVcb.route, direction);
+                            } else {
+                                mVcb.vcb.onVolumeSetRequest(mVcb.route, value);
+                            }
+                        }
+                    }
+                });
+            }
+        };
+
         void routeUpdated() {
             updateRoute(this);
         }
@@ -757,10 +877,14 @@
          * RemoteControlClient will be used to reflect and update information
          * such as route volume info in related UIs.</p>
          *
+         * <p>The RemoteControlClient must have been previously registered with
+         * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}.</p>
+         *
          * @param rcc RemoteControlClient associated with this route
          */
         public void setRemoteControlClient(RemoteControlClient rcc) {
             mRcc = rcc;
+            updatePlaybackInfoOnRcc();
         }
 
         /**
@@ -792,6 +916,111 @@
         public void setIconResource(int resId) {
             setIconDrawable(sStatic.mResources.getDrawable(resId));
         }
+
+        /**
+         * @hide (to be un-hidden)
+         * Set a callback to be notified of volume update requests
+         * @param vcb
+         */
+        public void setVolumeCallback(VolumeCallback vcb) {
+            mVcb = new VolumeCallbackInfo(vcb, this);
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * Defines whether playback associated with this route is "local"
+         *    ({@link RouteInfo#PLAYBACK_TYPE_LOCAL}) or "remote"
+         *    ({@link RouteInfo#PLAYBACK_TYPE_REMOTE}).
+         * @param type
+         */
+        public void setPlaybackType(int type) {
+            if (mPlaybackType != type) {
+                mPlaybackType = type;
+                setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, type);
+            }
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * Defines whether volume for the playback associated with this route is fixed
+         * ({@link RouteInfo#PLAYBACK_VOLUME_FIXED}) or can modified
+         * ({@link RouteInfo#PLAYBACK_VOLUME_VARIABLE}).
+         * @param volumeHandling
+         */
+        public void setVolumeHandling(int volumeHandling) {
+            if (mVolumeHandling != volumeHandling) {
+                mVolumeHandling = volumeHandling;
+                setPlaybackInfoOnRcc(
+                        RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, volumeHandling);
+            }
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * Defines at what volume the playback associated with this route is performed (for user
+         * feedback purposes). This information is only used when the playback is not local.
+         * @param volume
+         */
+        public void setVolume(int volume) {
+            if (mVolume != volume) {
+                mVolume = volume;
+                setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME, volume);
+            }
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * Defines the maximum volume at which the playback associated with this route is performed
+         * (for user feedback purposes). This information is only used when the playback is not
+         * local.
+         * @param volumeMax
+         */
+        public void setVolumeMax(int volumeMax) {
+            if (mVolumeMax != volumeMax) {
+                mVolumeMax = volumeMax;
+                setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, volumeMax);
+            }
+        }
+
+        /**
+         * @hide (to be un-hidden)
+         * Defines over what stream type the media is presented.
+         * @param stream
+         */
+        public void setPlaybackStream(int stream) {
+            if (mPlaybackStream != stream) {
+                mPlaybackStream = stream;
+                setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_USES_STREAM, stream);
+            }
+        }
+
+        private void updatePlaybackInfoOnRcc() {
+            if ((mRcc != null) && (mRcc.getRcseId() != RemoteControlClient.RCSE_ID_UNREGISTERED)) {
+                mRcc.setPlaybackInformation(
+                        RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, mVolumeMax);
+                mRcc.setPlaybackInformation(
+                        RemoteControlClient.PLAYBACKINFO_VOLUME, mVolume);
+                mRcc.setPlaybackInformation(
+                        RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, mVolumeHandling);
+                mRcc.setPlaybackInformation(
+                        RemoteControlClient.PLAYBACKINFO_USES_STREAM, mPlaybackStream);
+                mRcc.setPlaybackInformation(
+                        RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, mPlaybackType);
+                // let AudioService know whom to call when remote volume needs to be updated
+                try {
+                    sStatic.mAudioService.registerRemoteVolumeObserverForRcc(
+                            mRcc.getRcseId() /* rccId */, mRemoteVolObserver /* rvo */);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error registering remote volume observer", e);
+                }
+            }
+        }
+
+        private void setPlaybackInfoOnRcc(int what, int value) {
+            if (mRcc != null) {
+                mRcc.setPlaybackInformation(what, value);
+            }
+        }
     }
 
     /**
@@ -1206,4 +1435,44 @@
         }
 
     }
+
+    static class VolumeCallbackInfo {
+        public final VolumeCallback vcb;
+        public final RouteInfo route;
+
+        public VolumeCallbackInfo(VolumeCallback vcb, RouteInfo route) {
+            this.vcb = vcb;
+            this.route = route;
+        }
+    }
+
+    /**
+     * @hide (to be un-hidden)
+     * Interface for receiving events about volume changes.
+     * All methods of this interface will be called from the application's main thread.
+     *
+     * <p>A VolumeCallback will only receive events relevant to routes that the callback
+     * was registered for.</p>
+     *
+     * @see UserRouteInfo#setVolumeCallback(VolumeCallback)
+     */
+    public static abstract class VolumeCallback {
+        /**
+         * Called when the volume for the route should be increased or decreased.
+         * @param info the route affected by this event
+         * @param direction an integer indicating whether the volume is to be increased
+         *     (positive value) or decreased (negative value).
+         *     For bundled changes, the absolute value indicates the number of changes
+         *     in the same direction, e.g. +3 corresponds to three "volume up" changes.
+         */
+        public abstract void onVolumeUpdateRequest(RouteInfo info, int direction);
+        /**
+         * Called when the volume for the route should be set to the given value
+         * @param info the route affected by this event
+         * @param volume an integer indicating the new volume value that should be used, always
+         *     between 0 and the value set by {@link UserRouteInfo#setVolumeMax(int)}.
+         */
+        public abstract void onVolumeSetRequest(RouteInfo info, int volume);
+    }
+
 }
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 5b8035e..79f9d37 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -134,13 +134,13 @@
     public final static int PLAYSTATE_NONE               = 0;
 
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * The default playback type, "local", indicating the presentation of the media is happening on
      * the same device (e.g. a phone, a tablet) as where it is controlled from.
      */
     public final static int PLAYBACK_TYPE_LOCAL = 0;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * A playback type indicating the presentation of the media is happening on
      * a different device (i.e. the remote device) than where it is controlled from.
      */
@@ -148,7 +148,7 @@
     private final static int PLAYBACK_TYPE_MIN = PLAYBACK_TYPE_LOCAL;
     private final static int PLAYBACK_TYPE_MAX = PLAYBACK_TYPE_REMOTE;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information indicating the playback volume is fixed, i.e. it cannot be controlled
      * from this object. An example of fixed playback volume is a remote player, playing over HDMI
      * where the user prefer to control the volume on the HDMI sink, rather than attenuate at the
@@ -157,7 +157,7 @@
      */
     public final static int PLAYBACK_VOLUME_FIXED = 0;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information indicating the playback volume is variable and can be controlled from
      * this object.
      * @see #PLAYBACKINFO_VOLUME_HANDLING.
@@ -173,34 +173,34 @@
     //==========================================
     // Public keys for playback information
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information that defines the type of playback associated with this
      * RemoteControlClient. See {@link #PLAYBACK_TYPE_LOCAL} and {@link #PLAYBACK_TYPE_REMOTE}.
      */
     public final static int PLAYBACKINFO_PLAYBACK_TYPE = 1;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information that defines at what volume the playback associated with this
      * RemoteControlClient is performed. This information is only used when the playback type is not
      * local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}).
      */
     public final static int PLAYBACKINFO_VOLUME = 2;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information that defines the maximum volume volume value that is supported
      * by the playback associated with this RemoteControlClient. This information is only used
      * when the playback type is not local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}).
      */
     public final static int PLAYBACKINFO_VOLUME_MAX = 3;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information that defines how volume is handled for the presentation of the media.
      * @see #PLAYBACK_VOLUME_FIXED
      * @see #PLAYBACK_VOLUME_VARIABLE
      */
     public final static int PLAYBACKINFO_VOLUME_HANDLING = 4;
     /**
-     * @hide (to be un-hidden)
+     * @hide
      * Playback information that defines over what stream type the media is presented.
      */
     public final static int PLAYBACKINFO_USES_STREAM = 5;
@@ -642,7 +642,7 @@
     private int mPlaybackStream = AudioManager.STREAM_MUSIC;
 
     /**
-     * @hide  (to be un-hidden)
+     * @hide
      * Set information describing information related to the playback of media so the system
      * can implement additional behavior to handle non-local playback usecases.
      * @param what a key to specify the type of information to set. Valid keys are
@@ -713,7 +713,7 @@
     }
 
     /**
-     * @hide  (to be un-hidden)
+     * @hide
      * Return playback information represented as an integer value.
      * @param what a key to specify the type of information to retrieve. Valid keys are
      *        {@link #PLAYBACKINFO_PLAYBACK_TYPE},
@@ -899,6 +899,13 @@
         mRcseId = id;
     }
 
+    /**
+     * @hide
+     */
+    public int getRcseId() {
+        return mRcseId;
+    }
+
     private EventHandler mEventHandler;
     private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
     private final static int MSG_REQUEST_METADATA = 2;