Remove MediaSessionEngine.CallbackStub

This CL also removes SessionCallbackLink.CallbackStub class
from the system API list.

Bug: 123500993
Test: make update-api -j; make -j;
      atest CtsMediaTestCases:android.media.cts.MediaSessionTest;
      atest CtsMediaTestCases:android.media.cts.MediaControllerTest;
Change-Id: I59b4d4ce058c53c82d816152039c51b109f0c245
diff --git a/api/system-current.txt b/api/system-current.txt
index 27f7300..e656f0c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3664,7 +3664,7 @@
   }
 
   public final class MediaSessionEngine implements java.lang.AutoCloseable {
-    ctor public MediaSessionEngine(@NonNull android.content.Context, @NonNull android.media.session.SessionLink, @NonNull android.media.session.SessionCallbackLink, @NonNull android.media.session.MediaSessionEngine.CallbackStub);
+    ctor public MediaSessionEngine(@NonNull android.content.Context, @NonNull android.media.session.SessionLink, @NonNull android.media.session.SessionCallbackLink);
     method public void close();
     method public String getCallingPackage();
     method @NonNull public android.media.session.MediaController getController();
@@ -3689,33 +3689,6 @@
     method public void setSessionActivity(@Nullable android.app.PendingIntent);
   }
 
-  public static final class MediaSessionEngine.CallbackStub {
-    ctor public MediaSessionEngine.CallbackStub();
-    method public void onAdjustVolume(String, int, int, android.media.session.ControllerCallbackLink, int);
-    method public void onCommand(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle, android.os.ResultReceiver);
-    method public void onCustomAction(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onFastForward(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onMediaButton(String, int, int, android.content.Intent, int, android.os.ResultReceiver);
-    method public void onMediaButtonFromController(String, int, int, android.media.session.ControllerCallbackLink, android.content.Intent);
-    method public void onNext(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPause(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPlay(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPlayFromMediaId(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPlayFromSearch(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPlayFromUri(String, int, int, android.media.session.ControllerCallbackLink, android.net.Uri, android.os.Bundle);
-    method public void onPrepare(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onPrepareFromMediaId(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPrepareFromSearch(String, int, int, android.media.session.ControllerCallbackLink, String, android.os.Bundle);
-    method public void onPrepareFromUri(String, int, int, android.media.session.ControllerCallbackLink, android.net.Uri, android.os.Bundle);
-    method public void onPrevious(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onRate(String, int, int, android.media.session.ControllerCallbackLink, android.media.Rating);
-    method public void onRewind(String, int, int, android.media.session.ControllerCallbackLink);
-    method public void onSeekTo(String, int, int, android.media.session.ControllerCallbackLink, long);
-    method public void onSetVolumeTo(String, int, int, android.media.session.ControllerCallbackLink, int);
-    method public void onSkipToTrack(String, int, int, android.media.session.ControllerCallbackLink, long);
-    method public void onStop(String, int, int, android.media.session.ControllerCallbackLink);
-  }
-
   public static interface MediaSessionEngine.MediaButtonEventDelegate {
     method public boolean onMediaButtonIntent(android.content.Intent);
   }
diff --git a/media/apex/java/android/media/session/MediaSessionEngine.java b/media/apex/java/android/media/session/MediaSessionEngine.java
index 31714e1..7fea90d 100644
--- a/media/apex/java/android/media/session/MediaSessionEngine.java
+++ b/media/apex/java/android/media/session/MediaSessionEngine.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -44,7 +43,6 @@
 import android.view.KeyEvent;
 import android.view.ViewConfiguration;
 
-import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.Objects;
 
@@ -60,10 +58,7 @@
     private final MediaSession.Token mSessionToken;
     private final MediaController mController;
     private final SessionLink mSessionLink;
-    private final SessionCallbackLink mCbLink;
 
-    // Do not change the name of mCallbackWrapper. Support lib accesses this by using reflection.
-    @UnsupportedAppUsage
     private CallbackMessageHandler mCallbackHandler;
     private VolumeProvider mVolumeProvider;
     private PlaybackState mPlaybackState;
@@ -78,14 +73,12 @@
      *
      * @param context The context to use to create the session.
      * @param sessionLink A session link for the binder of MediaSessionRecord
-     * @param cbStub A callback link that handles incoming command to {@link MediaSession.Callback}.
      */
     public MediaSessionEngine(@NonNull Context context, @NonNull SessionLink sessionLink,
-            @NonNull SessionCallbackLink cbLink, @NonNull CallbackStub cbStub) {
+            @NonNull SessionCallbackLink cbLink) {
         mSessionLink = sessionLink;
-        mCbLink = cbLink;
 
-        cbStub.setSessionImpl(this);
+        cbLink.setSessionEngine(this);
         mSessionToken = new MediaSession.Token(mSessionLink.getController());
         mController = new MediaController(context, mSessionToken);
     }
@@ -479,97 +472,97 @@
         }
     }
 
-    private void dispatchPrepare(RemoteUserInfo caller) {
+    void dispatchPrepare(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE, null, null);
     }
 
-    private void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
+    void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras);
     }
 
-    private void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
+    void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras);
     }
 
-    private void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
+    void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_URI, uri, extras);
     }
 
-    private void dispatchPlay(RemoteUserInfo caller) {
+    void dispatchPlay(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY, null, null);
     }
 
-    private void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
+    void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras);
     }
 
-    private void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
+    void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
     }
 
-    private void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
+    void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
         postToCallback(caller, CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
     }
 
-    private void dispatchSkipToItem(RemoteUserInfo caller, long id) {
+    void dispatchSkipToItem(RemoteUserInfo caller, long id) {
         postToCallback(caller, CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, null);
     }
 
-    private void dispatchPause(RemoteUserInfo caller) {
+    void dispatchPause(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PAUSE, null, null);
     }
 
-    private void dispatchStop(RemoteUserInfo caller) {
+    void dispatchStop(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_STOP, null, null);
     }
 
-    private void dispatchNext(RemoteUserInfo caller) {
+    void dispatchNext(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_NEXT, null, null);
     }
 
-    private void dispatchPrevious(RemoteUserInfo caller) {
+    void dispatchPrevious(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_PREVIOUS, null, null);
     }
 
-    private void dispatchFastForward(RemoteUserInfo caller) {
+    void dispatchFastForward(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_FAST_FORWARD, null, null);
     }
 
-    private void dispatchRewind(RemoteUserInfo caller) {
+    void dispatchRewind(RemoteUserInfo caller) {
         postToCallback(caller, CallbackMessageHandler.MSG_REWIND, null, null);
     }
 
-    private void dispatchSeekTo(RemoteUserInfo caller, long pos) {
+    void dispatchSeekTo(RemoteUserInfo caller, long pos) {
         postToCallback(caller, CallbackMessageHandler.MSG_SEEK_TO, pos, null);
     }
 
-    private void dispatchRate(RemoteUserInfo caller, Rating rating) {
+    void dispatchRate(RemoteUserInfo caller, Rating rating) {
         postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null);
     }
 
-    private void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
+    void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
         postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
     }
 
-    private void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) {
+    void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) {
         postToCallback(caller, CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, null);
     }
 
-    private void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent,
+    void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent,
             long delay) {
         postToCallbackDelayed(info, CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
                 mediaButtonIntent, null, delay);
     }
 
-    private void dispatchAdjustVolume(RemoteUserInfo caller, int direction) {
+    void dispatchAdjustVolume(RemoteUserInfo caller, int direction) {
         postToCallback(caller, CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, null);
     }
 
-    private void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) {
+    void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) {
         postToCallback(caller, CallbackMessageHandler.MSG_SET_VOLUME, volume, null);
     }
 
-    private void dispatchCommand(RemoteUserInfo caller, String command, Bundle args,
+    void dispatchCommand(RemoteUserInfo caller, String command, Bundle args,
             ResultReceiver resultCb) {
         Command cmd = new Command(command, args, resultCb);
         postToCallback(caller, CallbackMessageHandler.MSG_COMMAND, cmd, null);
@@ -979,259 +972,7 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @SystemApi
-    public static final class CallbackStub extends SessionCallbackLink.CallbackStub {
-        private WeakReference<MediaSessionEngine> mSessionImpl;
-
-        private static RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid) {
-            return new RemoteUserInfo(packageName, pid, uid);
-        }
-
-        public CallbackStub() {
-        }
-
-        @Override
-        public void onCommand(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String command, Bundle args, ResultReceiver cb) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchCommand(createRemoteUserInfo(packageName, pid, uid),
-                        command, args, cb);
-            }
-        }
-
-        @Override
-        public void onMediaButton(String packageName, int pid, int uid, Intent mediaButtonIntent,
-                int sequenceNumber, ResultReceiver cb) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            try {
-                if (sessionImpl != null) {
-                    sessionImpl.dispatchMediaButton(
-                            createRemoteUserInfo(packageName, pid, uid), mediaButtonIntent);
-                }
-            } finally {
-                if (cb != null) {
-                    cb.send(sequenceNumber, null);
-                }
-            }
-        }
-
-        @Override
-        public void onMediaButtonFromController(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, Intent mediaButtonIntent) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid),
-                        mediaButtonIntent);
-            }
-        }
-
-        @Override
-        public void onPrepare(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onPrepareFromMediaId(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String mediaId,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepareFromMediaId(
-                        createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
-            }
-        }
-
-        @Override
-        public void onPrepareFromSearch(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String query,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepareFromSearch(
-                        createRemoteUserInfo(packageName, pid, uid), query, extras);
-            }
-        }
-
-        @Override
-        public void onPrepareFromUri(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, Uri uri, Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrepareFromUri(
-                        createRemoteUserInfo(packageName, pid, uid), uri, extras);
-            }
-        }
-
-        @Override
-        public void onPlay(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlay(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onPlayFromMediaId(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String mediaId,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlayFromMediaId(
-                        createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
-            }
-        }
-
-        @Override
-        public void onPlayFromSearch(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String query,
-                Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlayFromSearch(
-                        createRemoteUserInfo(packageName, pid, uid), query, extras);
-            }
-        }
-
-        @Override
-        public void onPlayFromUri(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, Uri uri, Bundle extras) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPlayFromUri(
-                        createRemoteUserInfo(packageName, pid, uid), uri, extras);
-            }
-        }
-
-        @Override
-        public void onSkipToTrack(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, long id) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchSkipToItem(
-                        createRemoteUserInfo(packageName, pid, uid), id);
-            }
-        }
-
-        @Override
-        public void onPause(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPause(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onStop(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchStop(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onNext(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchNext(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onPrevious(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onFastForward(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchFastForward(
-                        createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onRewind(String packageName, int pid, int uid,
-                ControllerCallbackLink caller) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchRewind(createRemoteUserInfo(packageName, pid, uid));
-            }
-        }
-
-        @Override
-        public void onSeekTo(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, long pos) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchSeekTo(
-                        createRemoteUserInfo(packageName, pid, uid), pos);
-            }
-        }
-
-        @Override
-        public void onRate(String packageName, int pid, int uid, ControllerCallbackLink caller,
-                Rating rating) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchRate(
-                        createRemoteUserInfo(packageName, pid, uid), rating);
-            }
-        }
-
-        @Override
-        public void onCustomAction(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, String action, Bundle args) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchCustomAction(
-                        createRemoteUserInfo(packageName, pid, uid), action, args);
-            }
-        }
-
-        @Override
-        public void onAdjustVolume(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, int direction) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchAdjustVolume(
-                        createRemoteUserInfo(packageName, pid, uid), direction);
-            }
-        }
-
-        @Override
-        public void onSetVolumeTo(String packageName, int pid, int uid,
-                ControllerCallbackLink caller, int value) {
-            MediaSessionEngine sessionImpl = mSessionImpl.get();
-            if (sessionImpl != null) {
-                sessionImpl.dispatchSetVolumeTo(
-                        createRemoteUserInfo(packageName, pid, uid), value);
-            }
-        }
-
-        void setSessionImpl(MediaSessionEngine sessionImpl) {
-            mSessionImpl = new WeakReference<>(sessionImpl);
-        }
-    }
-
-    /**
+     /**
      * A single item that is part of the play queue. It contains a description
      * of the item and its id in the queue.
      */
diff --git a/media/apex/java/android/media/session/SessionCallbackLink.java b/media/apex/java/android/media/session/SessionCallbackLink.java
index 3bcb65c..4c2918a 100644
--- a/media/apex/java/android/media/session/SessionCallbackLink.java
+++ b/media/apex/java/android/media/session/SessionCallbackLink.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.media.Rating;
+import android.media.session.MediaSessionManager.RemoteUserInfo;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -35,6 +36,8 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 
+import java.lang.ref.WeakReference;
+
 /**
  * Handles incoming commands to {@link MediaSession.Callback}.
  * @hide
@@ -42,16 +45,15 @@
 @SystemApi
 public final class SessionCallbackLink implements Parcelable {
     final Context mContext;
-    final CallbackStub mCallbackStub;
     final ISessionCallback mISessionCallback;
 
     /**
      * Constructor for stub (Callee)
+     * @hide
      */
-    SessionCallbackLink(@NonNull Context context, @NonNull CallbackStub callbackStub) {
+    public SessionCallbackLink(@NonNull Context context) {
         mContext = context;
-        mCallbackStub = callbackStub;
-        mISessionCallback = new CallbackStubProxy();
+        mISessionCallback = new CallbackStub();
     }
 
     /**
@@ -59,11 +61,19 @@
      */
     public SessionCallbackLink(IBinder binder) {
         mContext = null;
-        mCallbackStub = null;
         mISessionCallback = ISessionCallback.Stub.asInterface(binder);
     }
 
     /**
+     * Set {@link MediaSessionEngine} which will be used by {@link CallbackStub}.
+     */
+    void setSessionEngine(@Nullable MediaSessionEngine sessionImpl) {
+        if (mISessionCallback instanceof CallbackStub) {
+            ((CallbackStub) mISessionCallback).mSessionImpl = new WeakReference<>(sessionImpl);
+        }
+    }
+
+    /**
      * Notify session that a controller sends a command.
      *
      * @param packageName the package name of the controller
@@ -540,139 +550,24 @@
                 }
             };
 
-    /**
-     * Class for Stub implementation
-     */
-    abstract static class CallbackStub {
-        /** Stub method for ISessionCallback.notifyCommand */
-        public void onCommand(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String command,
-                @Nullable Bundle args, @Nullable ResultReceiver cb) {
+    private class CallbackStub extends ISessionCallback.Stub {
+        private WeakReference<MediaSessionEngine> mSessionImpl;
+
+        private RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid) {
+            return new RemoteUserInfo(packageName, pid, uid);
         }
 
-        /** Stub method for ISessionCallback.notifyMediaButton */
-        public void onMediaButton(@NonNull String packageName, int pid, int uid,
-                @NonNull Intent mediaButtonIntent, int sequenceNumber,
-                @Nullable ResultReceiver cb) {
-        }
-
-        /** Stub method for ISessionCallback.notifyMediaButtonFromController */
-        public void onMediaButtonFromController(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Intent mediaButtonIntent) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepare */
-        public void onPrepare(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepareFromMediaId */
-        public void onPrepareFromMediaId(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepareFromSearch */
-        public void onPrepareFromSearch(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, String query, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrepareFromUri */
-        public void onPrepareFromUri(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlay */
-        public void onPlay(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlayFromMediaId */
-        public void onPlayFromMediaId(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String mediaId,
-                @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlayFromSearch */
-        public void onPlayFromSearch(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, String query, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPlayFromUri */
-        public void onPlayFromUri(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Uri uri, @Nullable Bundle extras) {
-        }
-
-        /** Stub method for ISessionCallback.notifySkipToTrack */
-        public void onSkipToTrack(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, long id) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPause */
-        public void onPause(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyStop */
-        public void onStop(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyNext */
-        public void onNext(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyPrevious */
-        public void onPrevious(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyFastForward */
-        public void onFastForward(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifyRewind */
-        public void onRewind(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller) {
-        }
-
-        /** Stub method for ISessionCallback.notifySeekTo */
-        public void onSeekTo(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, long pos) {
-        }
-
-        /** Stub method for ISessionCallback.notifyRate */
-        public void onRate(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull Rating rating) {
-        }
-
-        /** Stub method for ISessionCallback.notifyCustomAction */
-        public void onCustomAction(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, @NonNull String action,
-                @Nullable Bundle args) {
-        }
-
-        /** Stub method for ISessionCallback.notifyAdjustVolume */
-        public void onAdjustVolume(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, int direction) {
-        }
-
-        /** Stub method for ISessionCallback.notifySetVolumeTo */
-        public void onSetVolumeTo(@NonNull String packageName, int pid, int uid,
-                @NonNull ControllerCallbackLink caller, int value) {
-        }
-    }
-
-    private class CallbackStubProxy extends ISessionCallback.Stub {
         @Override
         public void notifyCommand(String packageName, int pid, int uid,
                 ControllerCallbackLink caller, String command, Bundle args, ResultReceiver cb) {
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onCommand(packageName, pid, uid, caller, command, args, cb);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchCommand(createRemoteUserInfo(packageName, pid, uid),
+                            command, args, cb);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -684,9 +579,15 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onMediaButton(packageName, pid, uid, mediaButtonIntent,
-                        sequenceNumber, cb);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchMediaButton(
+                            createRemoteUserInfo(packageName, pid, uid), mediaButtonIntent);
+                }
             } finally {
+                if (cb != null) {
+                    cb.send(sequenceNumber, null);
+                }
                 Binder.restoreCallingIdentity(token);
             }
         }
@@ -697,8 +598,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onMediaButtonFromController(packageName, pid, uid, caller,
-                        mediaButtonIntent);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid),
+                            mediaButtonIntent);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -710,7 +614,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepare(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -722,7 +629,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepareFromMediaId(
+                            createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -734,7 +645,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepareFromSearch(
+                            createRemoteUserInfo(packageName, pid, uid), query, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -746,7 +661,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrepareFromUri(
+                            createRemoteUserInfo(packageName, pid, uid), uri, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -758,7 +677,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlay(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlay(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -770,7 +692,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlayFromMediaId(
+                            createRemoteUserInfo(packageName, pid, uid), mediaId, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -782,7 +708,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlayFromSearch(
+                            createRemoteUserInfo(packageName, pid, uid), query, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -794,7 +724,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPlayFromUri(
+                            createRemoteUserInfo(packageName, pid, uid), uri, extras);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -806,7 +740,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onSkipToTrack(packageName, pid, uid, caller, id);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchSkipToItem(
+                            createRemoteUserInfo(packageName, pid, uid), id);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -818,7 +756,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPause(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPause(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -830,7 +771,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onStop(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchStop(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -842,7 +786,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onNext(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchNext(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -854,7 +801,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onPrevious(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -866,7 +816,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onFastForward(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchFastForward(
+                            createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -878,7 +832,10 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onRewind(packageName, pid, uid, caller);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchRewind(createRemoteUserInfo(packageName, pid, uid));
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -890,7 +847,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onSeekTo(packageName, pid, uid, caller, pos);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchSeekTo(
+                            createRemoteUserInfo(packageName, pid, uid), pos);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -902,7 +863,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onRate(packageName, pid, uid, caller, rating);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchRate(
+                            createRemoteUserInfo(packageName, pid, uid), rating);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -913,7 +878,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onCustomAction(packageName, pid, uid, caller, action, args);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchCustomAction(
+                            createRemoteUserInfo(packageName, pid, uid), action, args);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -925,7 +894,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onAdjustVolume(packageName, pid, uid, caller, direction);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchAdjustVolume(
+                            createRemoteUserInfo(packageName, pid, uid), direction);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -937,7 +910,11 @@
             ensureMediaControlPermission();
             final long token = Binder.clearCallingIdentity();
             try {
-                mCallbackStub.onSetVolumeTo(packageName, pid, uid, caller, value);
+                MediaSessionEngine sessionImpl = mSessionImpl.get();
+                if (sessionImpl != null) {
+                    sessionImpl.dispatchSetVolumeTo(
+                            createRemoteUserInfo(packageName, pid, uid), value);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index ca3346c..03627de 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -142,10 +142,9 @@
         MediaSessionManager manager = (MediaSessionManager) context
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         try {
-            MediaSessionEngine.CallbackStub cbStub = new MediaSessionEngine.CallbackStub();
-            SessionCallbackLink cbLink = new SessionCallbackLink(context, cbStub);
+            SessionCallbackLink cbLink = new SessionCallbackLink(context);
             SessionLink sessionLink = manager.createSession(cbLink, tag);
-            mImpl = new MediaSessionEngine(context, sessionLink, cbLink, cbStub);
+            mImpl = new MediaSessionEngine(context, sessionLink, cbLink);
             mMaxBitmapSize = context.getResources().getDimensionPixelSize(
                     android.R.dimen.config_mediaMetadataBitmapMaxSize);
         } catch (RuntimeException e) {