Update user cache when coming from isAppCloneUserPair().

When we start a new user that shares media with its parent, we first ask
vold to mount the FUSE filesystem and issue bind mounts. These bind
mounts are for user 10, which causes isAppCloneUserPair(0, 10) to be
invoked. At this point, we haven't updated our user cache yet, because
StorageManagerService hasn't told us about this volume yet.

The simplest fix here is to update the user cache by default if we can't
find a user. The only place where we can't update the cache is when
we're handling a binder transaction, but that should be ok, since we
wouldn't expect any binder transactions for this volume until it is
mounted anyway.

Bug: 187904310
Bug: 192013761
Test: atest CtsAppCloningHostTest
Change-Id: I927d80b23b1568012436ab87df4460e92893e8e8
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 83d30db..6d5e623 100644
--- a/src/com/android/providers/media/util/UserCache.java
+++ b/src/com/android/providers/media/util/UserCache.java
@@ -111,16 +111,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);
         }
     }
 }