Merge "Update user cache when coming from isAppCloneUserPair()." into sc-dev
diff --git a/src/com/android/providers/media/LocalCallingIdentity.java b/src/com/android/providers/media/LocalCallingIdentity.java
index 60b4e0e..77a4c6b 100644
--- a/src/com/android/providers/media/LocalCallingIdentity.java
+++ b/src/com/android/providers/media/LocalCallingIdentity.java
@@ -130,7 +130,12 @@
         } else {
             user = UserHandle.getUserHandleForUid(binderUid);
         }
-        if (!userCache.userSharesMediaWithParent(user)) {
+        // We need to use the cached variant here, because the uncached version may
+        // make a binder transaction, which would cause infinite recursion here.
+        // Using the cached variant is fine, because we shouldn't be getting any binder
+        // requests for this volume before it has been mounted anyway, at which point
+        // we must already know about the new user.
+        if (!userCache.userSharesMediaWithParentCached(user)) {
             // It's possible that we got a cross-profile intent from a regular work profile; in
             // that case, the request was explicitly targeted at the media database of the owner
             // user; reflect that here.
diff --git a/src/com/android/providers/media/util/UserCache.java b/src/com/android/providers/media/util/UserCache.java
index 3db82c4..38d5326 100644
--- a/src/com/android/providers/media/util/UserCache.java
+++ b/src/com/android/providers/media/util/UserCache.java
@@ -117,16 +117,36 @@
 
     /**
      *  Returns whether the passed in user shares media with its parent (or peer).
+     *
+     * @param user user to check
+     * @return whether the user shares media with its parent
+     */
+    public boolean userSharesMediaWithParent(@NonNull UserHandle user) {
+        if (Process.myUserHandle().equals(user)) {
+            // Early return path - the owner user doesn't have a parent
+            return false;
+        }
+        boolean found = userSharesMediaWithParentCached(user);
+        if (!found) {
+            // Update the cache and try again
+            update();
+            found = userSharesMediaWithParentCached(user);
+        }
+        return found;
+    }
+
+    /**
+     *  Returns whether the passed in user shares media with its parent (or peer).
      *  Note that the value returned here is based on cached data; it relies on
      *  other callers to keep the user cache up-to-date.
      *
      * @param user user to check
      * @return whether the user shares media with its parent
      */
-    public boolean userSharesMediaWithParent(@NonNull UserHandle user) {
+    public boolean userSharesMediaWithParentCached(@NonNull UserHandle user) {
         synchronized (mLock) {
             // It must be a user that we manage, and not equal to the main user that we run as
-            return user != Process.myUserHandle() && mUsers.contains(user);
+            return !Process.myUserHandle().equals(user) && mUsers.contains(user);
         }
     }
 }