[go: nahoru, domu]

Media: Use PID information from the controller

Currently, MediaBrowserServiceCompat and Media2 had used
Binder#getCallingPid() to get the caller's PID. However,
Binder#getCallingPid() always returns 0 for oneway calls from a remote
process while MediaBrowserServiceCompat and Media2's only uses oneway
calls.

This CL does two things to address the PID issue.
  1. Caller sends the PID information.
     There's no other way to get caller PID information for oneway
     calls. Note that PID may not be available if caller didn't sent
     the PID (e.g. MediaBrowserCompat compiled with the older supportlib
     library wouldn't send PID information)
  2. Skips PID check in RemoteUserInfo#equals() when PID is unknown.

Bug: 111418518, Bug: 111418519
Test: $ ./gradlew media:connectedCheck media2:connectedCheck
      $ media/version-compat-tests/runtest.sh 4
      $ media2/version-compat-tests/runtest.sh 1
Change-Id: I8733a4d8538bcb482c177240bdbd60e6625c3d5d
diff --git a/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java b/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java
index 8a1c08d..b5296aa 100644
--- a/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java
+++ b/media/src/main/java/android/support/v4/media/MediaBrowserCompat.java
@@ -28,6 +28,7 @@
 import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
 import static androidx.media.MediaBrowserProtocol.CLIENT_VERSION_CURRENT;
 import static androidx.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
+import static androidx.media.MediaBrowserProtocol.DATA_CALLING_PID;
 import static androidx.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
 import static androidx.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION_EXTRAS;
 import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_ID;
@@ -40,6 +41,7 @@
 import static androidx.media.MediaBrowserProtocol.DATA_ROOT_HINTS;
 import static androidx.media.MediaBrowserProtocol.DATA_SEARCH_EXTRAS;
 import static androidx.media.MediaBrowserProtocol.DATA_SEARCH_QUERY;
+import static androidx.media.MediaBrowserProtocol.EXTRA_CALLING_PID;
 import static androidx.media.MediaBrowserProtocol.EXTRA_CLIENT_VERSION;
 import static androidx.media.MediaBrowserProtocol.EXTRA_MESSENGER_BINDER;
 import static androidx.media.MediaBrowserProtocol.EXTRA_SERVICE_VERSION;
@@ -64,6 +66,7 @@
 import android.os.Messenger;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.os.RemoteException;
 import android.support.v4.media.session.IMediaSession;
 import android.support.v4.media.session.MediaControllerCompat.TransportControls;
@@ -1633,6 +1636,7 @@
             mContext = context;
             mRootHints = (rootHints != null ? new Bundle(rootHints) : new Bundle());
             mRootHints.putInt(EXTRA_CLIENT_VERSION, CLIENT_VERSION_CURRENT);
+            mRootHints.putInt(EXTRA_CALLING_PID, Process.myPid());
             callback.setInternalConnectionCallback(this);
             mBrowserFwk = new MediaBrowser(context, serviceComponent,
                     callback.mConnectionCallbackFwk, mRootHints);
@@ -2160,6 +2164,7 @@
                 throws RemoteException {
             Bundle data = new Bundle();
             data.putString(DATA_PACKAGE_NAME, context.getPackageName());
+            data.putInt(DATA_CALLING_PID, Process.myPid());
             data.putBundle(DATA_ROOT_HINTS, mRootHints);
             sendRequest(CLIENT_MSG_CONNECT, data, callbacksMessenger);
         }
@@ -2199,6 +2204,7 @@
                 throws RemoteException {
             Bundle data = new Bundle();
             data.putString(DATA_PACKAGE_NAME, context.getPackageName());
+            data.putInt(DATA_CALLING_PID, Process.myPid());
             data.putBundle(DATA_ROOT_HINTS, mRootHints);
             sendRequest(CLIENT_MSG_REGISTER_CALLBACK_MESSENGER, data, callbackMessenger);
         }
diff --git a/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java b/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
index 100e64b..69b8859 100644
--- a/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
+++ b/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
@@ -2198,12 +2198,18 @@
                     Bundle data = new Bundle();
 
                     int uid = Binder.getCallingUid();
+                    data.putInt(DATA_CALLING_UID, uid);
                     // Note: Different apps can have same uid, but only when they are signed with
                     // the same private key. This means those apps are from the same developer.
                     // Session apps can allow/reject controller by reading one of their names.
                     data.putString(DATA_CALLING_PACKAGE, getPackageNameForUid(uid));
-                    data.putInt(DATA_CALLING_PID, Binder.getCallingPid());
-                    data.putInt(DATA_CALLING_UID, uid);
+                    int pid = Binder.getCallingPid();
+                    if (pid > 0) {
+                        data.putInt(DATA_CALLING_PID, pid);
+                    } else if (data.getLong(DATA_CALLING_PID, UNKNOWN_PID) == UNKNOWN_PID) {
+                        // This cannot be happen for now, but added for future changes.
+                        data.putInt(DATA_CALLING_PID, UNKNOWN_PID);
+                    }
                     if (extras != null) {
                         data.putBundle(DATA_EXTRAS, extras);
                     }
diff --git a/media/src/main/java/androidx/media/MediaBrowserProtocol.java b/media/src/main/java/androidx/media/MediaBrowserProtocol.java
index eb5b449..ddd3283 100644
--- a/media/src/main/java/androidx/media/MediaBrowserProtocol.java
+++ b/media/src/main/java/androidx/media/MediaBrowserProtocol.java
@@ -46,6 +46,7 @@
     public static final String DATA_CUSTOM_ACTION_EXTRAS = "data_custom_action_extras";
 
     public static final String EXTRA_CLIENT_VERSION = "extra_client_version";
+    public static final String EXTRA_CALLING_PID = "extra_calling_pid";
     public static final String EXTRA_SERVICE_VERSION = "extra_service_version";
     public static final String EXTRA_MESSENGER_BINDER = "extra_messenger";
     public static final String EXTRA_SESSION_BINDER = "extra_session_binder";
diff --git a/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java b/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java
index 6341950..b36949d 100644
--- a/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java
+++ b/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java
@@ -42,6 +42,7 @@
 import static androidx.media.MediaBrowserProtocol.DATA_ROOT_HINTS;
 import static androidx.media.MediaBrowserProtocol.DATA_SEARCH_EXTRAS;
 import static androidx.media.MediaBrowserProtocol.DATA_SEARCH_QUERY;
+import static androidx.media.MediaBrowserProtocol.EXTRA_CALLING_PID;
 import static androidx.media.MediaBrowserProtocol.EXTRA_CLIENT_VERSION;
 import static androidx.media.MediaBrowserProtocol.EXTRA_MESSENGER_BINDER;
 import static androidx.media.MediaBrowserProtocol.EXTRA_SERVICE_VERSION;
@@ -50,6 +51,7 @@
 import static androidx.media.MediaBrowserProtocol.SERVICE_MSG_ON_CONNECT_FAILED;
 import static androidx.media.MediaBrowserProtocol.SERVICE_MSG_ON_LOAD_CHILDREN;
 import static androidx.media.MediaBrowserProtocol.SERVICE_VERSION_CURRENT;
+import static androidx.media.MediaSessionManager.RemoteUserInfo.UNKNOWN_PID;
 
 import android.app.Service;
 import android.content.Context;
@@ -179,6 +181,7 @@
     private @interface ResultFlags {
     }
 
+    final ArrayList<ConnectionRecord> mPendingConnections = new ArrayList<>();
     final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
     ConnectionRecord mCurConnection;
     final ServiceHandler mHandler = new ServiceHandler();
@@ -347,6 +350,7 @@
         public BrowserRoot onGetRoot(
                 String clientPackageName, int clientUid, Bundle rootHints) {
             Bundle rootExtras = null;
+            int clientPid = UNKNOWN_PID;
             if (rootHints != null && rootHints.getInt(EXTRA_CLIENT_VERSION, 0) != 0) {
                 rootHints.remove(EXTRA_CLIENT_VERSION);
                 mMessenger = new Messenger(mHandler);
@@ -360,17 +364,27 @@
                 } else {
                     mRootExtrasList.add(rootExtras);
                 }
+                clientPid = rootHints.getInt(EXTRA_CALLING_PID, UNKNOWN_PID);
+                rootHints.remove(EXTRA_CALLING_PID);
             }
+            ConnectionRecord connection = new ConnectionRecord(
+                    clientPackageName, clientPid, clientUid, rootHints, null);
             // We aren't sure whether this connection request would be accepted.
             // Temporarily set mCurConnection just to make getCurrentBrowserInfo() working.
-            mCurConnection = new ConnectionRecord(clientPackageName, -1, clientUid, rootHints,
-                    null);
+            mCurConnection = connection;
             BrowserRoot root = MediaBrowserServiceCompat.this.onGetRoot(
                     clientPackageName, clientUid, rootHints);
             mCurConnection = null;
             if (root == null) {
                 return null;
             }
+            if (mMessenger != null) {
+                // Keeps the connection request from the MediaBrowserCompat to reuse the package
+                // name here.
+                // Note: Connection will be completed after it gets extra binder call with
+                // CLIENT_MSG_REGISTER_CALLBACK_MESSENGER.
+                mPendingConnections.add(connection);
+            }
             if (rootExtras == null) {
                 rootExtras = root.getExtras();
             } else if (root.getExtras() != null) {
@@ -729,7 +743,12 @@
             Bundle data = msg.getData();
             data.setClassLoader(MediaBrowserCompat.class.getClassLoader());
             data.putInt(DATA_CALLING_UID, Binder.getCallingUid());
-            data.putInt(DATA_CALLING_PID, Binder.getCallingPid());
+            int pid = Binder.getCallingPid();
+            if (pid > 0) {
+                data.putInt(DATA_CALLING_PID, pid);
+            } else if (data.getLong(DATA_CALLING_PID, UNKNOWN_PID) == UNKNOWN_PID) {
+                data.putInt(DATA_CALLING_PID, UNKNOWN_PID);
+            }
             return super.sendMessageAtTime(msg, uptimeMillis);
         }
 
@@ -1064,8 +1083,25 @@
                     // Clear out the old subscriptions. We are getting new ones.
                     mConnections.remove(b);
 
-                    final ConnectionRecord connection = new ConnectionRecord(pkg, pid, uid,
-                            rootHints, callbacks);
+                    ConnectionRecord connection = null;
+                    for (ConnectionRecord pendingConnection : mPendingConnections) {
+                        // Note: We cannot use Map/Set for mPendingConnections but List because
+                        // multiple MediaBrowserCompats with the same UID can request connect.
+                        if (pendingConnection.uid == uid) {
+                            // If caller hasn't set pkg and pid, do the best effort to get it.
+                            if (TextUtils.isEmpty(pkg) || pid <= 0) {
+                                // Note: Do not assign pendingConnection directly because it doesn't
+                                // have callback information.
+                                connection = new ConnectionRecord(pendingConnection.pkg,
+                                        pendingConnection.pid, pendingConnection.uid,
+                                        rootHints, callbacks);
+                            }
+                            mPendingConnections.remove(pendingConnection);
+                        }
+                    }
+                    if (connection == null) {
+                        connection = new ConnectionRecord(pkg, pid, uid, rootHints, callbacks);
+                    }
                     mConnections.put(b, connection);
                     try {
                         b.linkToDeath(connection, 0);
diff --git a/media/src/main/java/androidx/media/MediaSessionManager.java b/media/src/main/java/androidx/media/MediaSessionManager.java
index e3fc0eb..ba9d256 100644
--- a/media/src/main/java/androidx/media/MediaSessionManager.java
+++ b/media/src/main/java/androidx/media/MediaSessionManager.java
@@ -20,7 +20,6 @@
 
 import android.content.Context;
 import android.os.Build;
-import android.support.v4.media.MediaBrowserCompat;
 import android.support.v4.media.session.MediaControllerCompat;
 import android.support.v4.media.session.MediaSessionCompat;
 import android.util.Log;
@@ -199,18 +198,15 @@
         }
 
         /**
-         * Returns equality of two RemoteUserInfo.
+         * Returns equality of two RemoteUserInfo by comparing their package name, UID, and PID.
          * <p>
-         * Prior to P (API < 28), two RemoteUserInfo objects are equal only if
-         * they are from same package and from same process.
-         * <p>
-         * On P and beyond (API >= 28), two RemoteUserInfo objects are equal only if they're sent
-         * from the same controller (either {@link MediaControllerCompat} or
-         * {@link MediaBrowserCompat}. If it's not nor one of them is triggered by the key presses,
-         * they would be considered as different one.
-         * <p>
-         * If you only want to compare the caller's package, compare them with the
-         * {@link #getPackageName()}, {@link #getPid()}, and/or {@link #getUid()} directly.
+         * On P and before (API <= 28), two RemoteUserInfo objects equal if following conditions are
+         * met:
+         * <ol>
+         * <li>UID and package name are the same</li>
+         * <li>One of the RemoteUserInfo's PID is {@link #UNKNOWN_PID} or both of RemoteUserInfo's
+         *     PID are the same</li>
+         * </ol>
          *
          * @param obj the reference object with which to compare.
          * @return {@code true} if equals, {@code false} otherwise
diff --git a/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java b/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java
index f8ff41f..e7971ce 100644
--- a/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java
+++ b/media/src/main/java/androidx/media/MediaSessionManagerImplApi28.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 
 import androidx.annotation.RequiresApi;
-import androidx.core.util.ObjectsCompat;
 
 @RequiresApi(28)
 class MediaSessionManagerImplApi28 extends MediaSessionManagerImplApi21 {
@@ -45,49 +44,36 @@
         return super.isTrustedForMediaControl(userInfo);
     }
 
-    static final class RemoteUserInfoImplApi28 implements MediaSessionManager.RemoteUserInfoImpl {
+    /**
+     * This extends {@link RemoteUserInfoImplBase} on purpose not to use frameworks' equals() and
+     * hashCode() implementation for two reasons:
+     *
+     *   1. To override PID checks when one of them are unknown.
+     *      PID can be unknown between MediaBrowserCompat / MediaBrowserServiceCompat
+     *   2. To skip checking hidden binder.
+     *      Framework's {@link android.media.session.MediaSessionManager.RemoteUserInfo} also checks
+     *      internal binder to distinguish multiple {@link android.media.session.MediaController}
+     *      and {@link android.media.browse.MediaBrowser} in a process. However, when the binders in
+     *      both RemoteUserInfos are {@link null}, framework's equal() specially handles the case
+     *      and returns {@code false}. This cause two issues that we need to workaround.
+     *         Issue a) RemoteUserInfos created by key events are considered as all different.
+     *         issue b) RemoteUserInfos created with public constructors are considers as all
+     *                  different.
+     */
+    static final class RemoteUserInfoImplApi28 extends RemoteUserInfoImplBase {
         final android.media.session.MediaSessionManager.RemoteUserInfo mObject;
 
         RemoteUserInfoImplApi28(String packageName, int pid, int uid) {
+            super(packageName, pid, uid);
             mObject = new android.media.session.MediaSessionManager.RemoteUserInfo(
                     packageName, pid, uid);
         }
 
         RemoteUserInfoImplApi28(
                 android.media.session.MediaSessionManager.RemoteUserInfo remoteUserInfo) {
+            super(remoteUserInfo.getPackageName(), remoteUserInfo.getPid(),
+                    remoteUserInfo.getUid());
             mObject = remoteUserInfo;
         }
-
-        @Override
-        public String getPackageName() {
-            return mObject.getPackageName();
-        }
-
-        @Override
-        public int getPid() {
-            return mObject.getPid();
-        }
-
-        @Override
-        public int getUid() {
-            return mObject.getUid();
-        }
-
-        @Override
-        public int hashCode() {
-            return ObjectsCompat.hash(mObject);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof RemoteUserInfoImplApi28)) {
-                return false;
-            }
-            RemoteUserInfoImplApi28 other = (RemoteUserInfoImplApi28) obj;
-            return mObject.equals(other.mObject);
-        }
     }
 }
diff --git a/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java b/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java
index de0c5ad..1a1d67dc 100644
--- a/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java
+++ b/media/src/main/java/androidx/media/MediaSessionManagerImplBase.java
@@ -16,6 +16,8 @@
 
 package androidx.media;
 
+import static androidx.media.MediaSessionManager.RemoteUserInfo.UNKNOWN_PID;
+
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -146,6 +148,11 @@
                 return false;
             }
             RemoteUserInfoImplBase otherUserInfo = (RemoteUserInfoImplBase) obj;
+            if (mPid == UNKNOWN_PID || otherUserInfo.mPid == UNKNOWN_PID) {
+                // Only compare package name and UID when PID is unknown.
+                return TextUtils.equals(mPackageName, otherUserInfo.mPackageName)
+                        && mUid == otherUserInfo.mUid;
+            }
             return TextUtils.equals(mPackageName, otherUserInfo.mPackageName)
                     && mPid == otherUserInfo.mPid
                     && mUid == otherUserInfo.mUid;
@@ -153,8 +160,7 @@
 
         @Override
         public int hashCode() {
-            return ObjectsCompat.hash(mPackageName, mPid, mUid);
+            return ObjectsCompat.hash(mPackageName, mUid);
         }
     }
 }
-
diff --git a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
index 5ed7fcf3..55dce08 100644
--- a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
+++ b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
@@ -73,7 +73,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -269,7 +268,6 @@
         if (Build.VERSION.SDK_INT >= 28) {
             assertEquals(Process.myUid(), remoteUserInfo2.getUid());
             assertEquals(Process.myPid(), remoteUserInfo2.getPid());
-            assertNotEquals(remoteUserInfo1, remoteUserInfo2);
         }
     }
 
diff --git a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
index d70ce8b..290950a 100644
--- a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
+++ b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/StubMediaBrowserServiceCompat.java
@@ -30,16 +30,20 @@
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_ERROR;
 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_NO_RESULT;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
 import android.os.Bundle;
+import android.support.mediacompat.testlib.util.IntentUtil;
 import android.support.v4.media.MediaBrowserCompat.MediaItem;
 import android.support.v4.media.MediaDescriptionCompat;
 import android.support.v4.media.MediaMetadataCompat;
 import android.support.v4.media.session.MediaSessionCompat;
+import android.text.TextUtils;
 
 import androidx.annotation.NonNull;
 import androidx.media.MediaBrowserServiceCompat;
+import androidx.media.MediaSessionManager.RemoteUserInfo;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -57,6 +61,7 @@
     private Result<List<MediaItem>> mPendingLoadChildrenResult;
     private Result<MediaItem> mPendingLoadItemResult;
     private Bundle mPendingRootHints;
+    private RemoteUserInfo mRemoteUserInfo;
 
     public Bundle mCustomActionExtras;
     public Result<Bundle> mCustomActionResult;
@@ -78,13 +83,18 @@
 
     @Override
     public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
+        if (!TextUtils.equals(clientPackageName, IntentUtil.CLIENT_PACKAGE_NAME)) {
+            return null;
+        }
         mExtras = new Bundle();
         mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
+        mRemoteUserInfo = getCurrentBrowserInfo();
         return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
     }
 
     @Override
     public void onLoadChildren(final String parentId, final Result<List<MediaItem>> result) {
+        assertEquals(mRemoteUserInfo, getCurrentBrowserInfo());
         List<MediaItem> mediaItems = new ArrayList<>();
         if (MEDIA_ID_ROOT.equals(parentId)) {
             Bundle rootHints = getBrowserRootHints();
@@ -105,6 +115,7 @@
     @Override
     public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaItem>> result,
             @NonNull Bundle options) {
+        assertEquals(mRemoteUserInfo, getCurrentBrowserInfo());
         if (MEDIA_ID_INCLUDE_METADATA.equals(parentId)) {
             // Test unparcelling the Bundle.
             MediaMetadataCompat metadata = options.getParcelable(MEDIA_METADATA);
@@ -122,6 +133,7 @@
 
     @Override
     public void onLoadItem(String itemId, Result<MediaItem> result) {
+        assertEquals(mRemoteUserInfo, getCurrentBrowserInfo());
         if (MEDIA_ID_CHILDREN_DELAYED.equals(itemId)) {
             mPendingLoadItemResult = result;
             mPendingRootHints = getBrowserRootHints();
@@ -147,6 +159,7 @@
 
     @Override
     public void onSearch(String query, Bundle extras, Result<List<MediaItem>> result) {
+        assertEquals(mRemoteUserInfo, getCurrentBrowserInfo());
         if (SEARCH_QUERY_FOR_NO_RESULT.equals(query)) {
             result.sendResult(Collections.<MediaItem>emptyList());
         } else if (SEARCH_QUERY_FOR_ERROR.equals(query)) {
@@ -164,6 +177,7 @@
 
     @Override
     public void onCustomAction(String action, Bundle extras, Result<Bundle> result) {
+        assertEquals(mRemoteUserInfo, getCurrentBrowserInfo());
         mCustomActionResult = result;
         mCustomActionExtras = extras;
         if (CUSTOM_ACTION_FOR_ERROR.equals(action)) {
diff --git a/media2/src/main/java/androidx/media2/ConnectedControllersManager.java b/media2/src/main/java/androidx/media2/ConnectedControllersManager.java
index d72e6f0..cf012b1 100644
--- a/media2/src/main/java/androidx/media2/ConnectedControllersManager.java
+++ b/media2/src/main/java/androidx/media2/ConnectedControllersManager.java
@@ -16,21 +16,17 @@
 
 package androidx.media2;
 
-import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.Nullable;
 import androidx.collection.ArrayMap;
-import androidx.core.util.ObjectsCompat;
-import androidx.media.MediaSessionManager.RemoteUserInfo;
 import androidx.media2.MediaSession.ControllerInfo;
 import androidx.media2.MediaSession.MediaSessionImpl;
 import androidx.media2.SessionCommand.CommandCode;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * Manages connected {@link ControllerInfo}. This is thread-safe.
@@ -54,6 +50,7 @@
     ConnectedControllersManager(MediaSessionImpl session) {
         mSessionImpl = session;
     }
+
     public void addController(T controllerKey, ControllerInfo controllerInfo,
             SessionCommandGroup commands) {
         if (controllerKey == null || controllerInfo == null) {
@@ -71,7 +68,7 @@
                         controllerKey, new SequencedFutureManager(), commands));
             } else {
                 // already exist. Only update allowed commands.
-                ConnectedControllerRecord record = mControllerRecords.get(controllerInfo);
+                ConnectedControllerRecord record = mControllerRecords.get(savedInfo);
                 record.allowedCommands = commands;
             }
         }
@@ -193,24 +190,8 @@
 
     public ControllerInfo getController(T controllerKey) {
         synchronized (mLock) {
-            for (Map.Entry<T, ControllerInfo> e : mControllerInfoMap.entrySet()) {
-                if (e.getKey() instanceof RemoteUserInfo) {
-                    // Only checks the package name and UID to workaround two things.
-                    // 1. In MediaBrowserServiceCompat, RemoteUserInfo from onGetRoot and other
-                    //    methods are differ even for the same controller.
-                    // 2. For key presses, RemoteUserInfo differs for individual key events.
-                    RemoteUserInfo remoteUserInfo = (RemoteUserInfo) e.getKey();
-                    RemoteUserInfo other = (RemoteUserInfo) controllerKey;
-                    if (TextUtils.equals(remoteUserInfo.getPackageName(), other.getPackageName())
-                            && remoteUserInfo.getUid() == other.getUid()) {
-                        return e.getValue();
-                    }
-                } else if (ObjectsCompat.equals(e.getKey(), controllerKey)) {
-                    return e.getValue();
-                }
-            }
+            return mControllerInfoMap.get(controllerKey);
         }
-        return null;
     }
 
     private class ConnectedControllerRecord {
diff --git a/media2/src/main/java/androidx/media2/ConnectionRequest.java b/media2/src/main/java/androidx/media2/ConnectionRequest.java
index 6eba078..68a99ed 100644
--- a/media2/src/main/java/androidx/media2/ConnectionRequest.java
+++ b/media2/src/main/java/androidx/media2/ConnectionRequest.java
@@ -32,15 +32,18 @@
     int mVersion;
     @ParcelField(1)
     String mPackageName;
+    @ParcelField(2)
+    int mPid;
 
     // For versioned parcelable.
     ConnectionRequest() {
         // no-op
     }
 
-    ConnectionRequest(String packageName) {
-        mPackageName = packageName;
+    ConnectionRequest(String packageName, int pid) {
         mVersion = MediaUtils.CURRENT_VERSION;
+        mPackageName = packageName;
+        mPid = pid;
     }
 
     public String getPackageName() {
@@ -50,4 +53,8 @@
     public int getVersion() {
         return mVersion;
     }
+
+    public int getPid() {
+        return mPid;
+    }
 }
diff --git a/media2/src/main/java/androidx/media2/MediaControllerImplBase.java b/media2/src/main/java/androidx/media2/MediaControllerImplBase.java
index e1b1734..26982a5 100644
--- a/media2/src/main/java/androidx/media2/MediaControllerImplBase.java
+++ b/media2/src/main/java/androidx/media2/MediaControllerImplBase.java
@@ -63,6 +63,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.support.v4.media.MediaBrowserCompat;
@@ -822,7 +823,8 @@
     private void connectToSession() {
         IMediaSession iSession = IMediaSession.Stub.asInterface((IBinder) mToken.getBinder());
         int seq = mSequencedFutureManager.obtainNextSequenceNumber();
-        ConnectionRequest request = new ConnectionRequest(mContext.getPackageName());
+        ConnectionRequest request =
+                new ConnectionRequest(mContext.getPackageName(), Process.myPid());
         try {
             iSession.connect(mControllerStub, seq, MediaUtils.toParcelable(request));
         } catch (RemoteException e) {
@@ -1193,7 +1195,8 @@
                 Log.wtf(TAG, "Service interface is missing.");
                 return;
             }
-            ConnectionRequest request = new ConnectionRequest(getContext().getPackageName());
+            ConnectionRequest request =
+                    new ConnectionRequest(getContext().getPackageName(), Process.myPid());
             try {
 
                 iService.connect(mControllerStub, MediaUtils.toParcelable(request));
diff --git a/media2/src/main/java/androidx/media2/MediaSessionServiceImplBase.java b/media2/src/main/java/androidx/media2/MediaSessionServiceImplBase.java
index 45d3e46..352ad5e 100644
--- a/media2/src/main/java/androidx/media2/MediaSessionServiceImplBase.java
+++ b/media2/src/main/java/androidx/media2/MediaSessionServiceImplBase.java
@@ -219,10 +219,11 @@
                 }
                 return;
             }
-            final int pid = Binder.getCallingPid();
+            final int callingPid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             final ConnectionRequest request = MediaUtils.fromParcelable(connectionRequest);
+            final int pid = (callingPid != 0) ? callingPid : request.getPid();
             final String packageName = connectionRequest == null ? null : request.getPackageName();
             try {
                 mHandler.post(new Runnable() {
diff --git a/media2/src/main/java/androidx/media2/MediaSessionStub.java b/media2/src/main/java/androidx/media2/MediaSessionStub.java
index aa48c9f..33c2e66 100644
--- a/media2/src/main/java/androidx/media2/MediaSessionStub.java
+++ b/media2/src/main/java/androidx/media2/MediaSessionStub.java
@@ -432,10 +432,13 @@
         if (caller == null || connectionRequest == null) {
             return;
         }
-        final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
         final long token = Binder.clearCallingIdentity();
         final ConnectionRequest request = MediaUtils.fromParcelable(connectionRequest);
+        // Binder.getCallingPid() can be 0 for an oneway call from the remote process.
+        // If it's the case, use PID from the ConnectionRequest.
+        final int pid = (callingPid != 0) ? callingPid : request.getPid();
         try {
             connect(caller, request.getPackageName(), pid, uid);
         } finally {