Merge "Update user cache when coming from isAppCloneUserPair()." into sc-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index c8dbf77..5b80e36 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -3,3 +3,6 @@
 
 [Builtin Hooks Options]
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+
+[Hook Scripts]
+hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
diff --git a/apex/Android.bp b/apex/Android.bp
index b620fe6..d53560a 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -50,4 +50,18 @@
     name: "com.android.mediaprovider-bootclasspath-fragment",
     contents: ["framework-mediaprovider"],
     apex_available: ["com.android.mediaprovider"],
+
+    // The bootclasspath_fragments that provide APIs on which this depends.
+    fragments: [
+        {
+            apex: "com.android.art",
+            module: "art-bootclasspath-fragment",
+        },
+    ],
+
+    // Additional hidden API flag files to override the defaults. This must only be
+    // modified by the Soong or platform compat team.
+    hidden_api: {
+        max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"],
+    },
 }
diff --git a/apex/hiddenapi/OWNERS b/apex/hiddenapi/OWNERS
new file mode 100644
index 0000000..ac8a2b6
--- /dev/null
+++ b/apex/hiddenapi/OWNERS
@@ -0,0 +1,5 @@
+# soong-team@ as the hiddenapi files are tightly coupled with Soong
+file:platform/build/soong:/OWNERS
+
+# compat-team@ for changes to hiddenapi files
+file:tools/platform-compat:/OWNERS
diff --git a/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt b/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
new file mode 100644
index 0000000..7c59c96
--- /dev/null
+++ b/apex/hiddenapi/hiddenapi-max-target-o-low-priority.txt
@@ -0,0 +1,27 @@
+Landroid/provider/MediaStore$Audio$AudioColumns;->ALBUM_ARTIST:Ljava/lang/String;
+Landroid/provider/MediaStore$Audio$AudioColumns;->COMPILATION:Ljava/lang/String;
+Landroid/provider/MediaStore$Audio$AudioColumns;->GENRE:Ljava/lang/String;
+Landroid/provider/MediaStore$Audio$AudioColumns;->TITLE_RESOURCE_URI:Ljava/lang/String;
+Landroid/provider/MediaStore$Audio$Media;->EXTERNAL_PATHS:[Ljava/lang/String;
+Landroid/provider/MediaStore$Audio$Radio;-><init>()V
+Landroid/provider/MediaStore$Files;->getDirectoryUri(Ljava/lang/String;)Landroid/net/Uri;
+Landroid/provider/MediaStore$Images$Media;->StoreThumbnail(Landroid/content/ContentResolver;Landroid/graphics/Bitmap;JFFI)Landroid/graphics/Bitmap;
+Landroid/provider/MediaStore$InternalThumbnails;-><init>()V
+Landroid/provider/MediaStore$InternalThumbnails;->cancelThumbnailRequest(Landroid/content/ContentResolver;JLandroid/net/Uri;J)V
+Landroid/provider/MediaStore$InternalThumbnails;->DEFAULT_GROUP_ID:I
+Landroid/provider/MediaStore$InternalThumbnails;->FULL_SCREEN_KIND:I
+Landroid/provider/MediaStore$InternalThumbnails;->getMiniThumbFromFile(Landroid/database/Cursor;Landroid/net/Uri;Landroid/content/ContentResolver;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
+Landroid/provider/MediaStore$InternalThumbnails;->getThumbnail(Landroid/content/ContentResolver;JJILandroid/graphics/BitmapFactory$Options;Landroid/net/Uri;Z)Landroid/graphics/Bitmap;
+Landroid/provider/MediaStore$InternalThumbnails;->MICRO_KIND:I
+Landroid/provider/MediaStore$InternalThumbnails;->MINI_KIND:I
+Landroid/provider/MediaStore$InternalThumbnails;->PROJECTION:[Ljava/lang/String;
+Landroid/provider/MediaStore$InternalThumbnails;->sThumbBuf:[B
+Landroid/provider/MediaStore$InternalThumbnails;->sThumbBufLock:Ljava/lang/Object;
+Landroid/provider/MediaStore$MediaColumns;->MEDIA_SCANNER_NEW_OBJECT_ID:Ljava/lang/String;
+Landroid/provider/MediaStore;->CONTENT_AUTHORITY_SLASH:Ljava/lang/String;
+Landroid/provider/MediaStore;->getDocumentUri(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/util/List;)Landroid/net/Uri;
+Landroid/provider/MediaStore;->getFilePath(Landroid/content/ContentResolver;Landroid/net/Uri;)Ljava/lang/String;
+Landroid/provider/MediaStore;->PARAM_DELETE_DATA:Ljava/lang/String;
+Landroid/provider/MediaStore;->RETRANSLATE_CALL:Ljava/lang/String;
+Landroid/provider/MediaStore;->TAG:Ljava/lang/String;
+Landroid/provider/MediaStore;->UNHIDE_CALL:Ljava/lang/String;
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 58cc9b0..e17e1e5 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -38,7 +38,7 @@
       <item quantity="one">他 <xliff:g id="COUNT_0">^1</xliff:g> 件の項目</item>
     </plurals>
     <string name="cache_clearing_dialog_title" msgid="8907893815183913664">"アプリの一時ファイルの削除"</string>
-    <string name="cache_clearing_dialog_text" msgid="7057784635111940957">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>が一部の一時ファイルを削除する権限を求めています。この処理により、電池やモバイルデータの使用量が増えることがあります。"</string>
+    <string name="cache_clearing_dialog_text" msgid="7057784635111940957">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>が一部の一時ファイルを削除する権限を求めています。この処理により、バッテリーやモバイルデータの使用量が増えることがあります。"</string>
     <string name="cache_clearing_in_progress_title" msgid="6902220064511664209">"アプリの一時ファイルを削除しています…"</string>
     <string name="clear" msgid="5524638938415865915">"削除"</string>
     <string name="allow" msgid="8885707816848569619">"許可"</string>
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index b2f6e8c..b29b3d7 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -1312,14 +1312,18 @@
         try {
             UserHandle user1 = UserHandle.of(userId1);
             UserHandle user2 = UserHandle.of(userId2);
-
-            if (SdkLevel.isAtLeastS() && (mUserCache.userSharesMediaWithParent(user1)
+            if (Build.VERSION.DEVICE_INITIAL_SDK_INT < Build.VERSION_CODES.S) {
+                if (SdkLevel.isAtLeastS() && (mUserCache.userSharesMediaWithParent(user1)
                     || mUserCache.userSharesMediaWithParent(user2))) {
-                return true;
-            }
-            Method isAppCloneUserPair = StorageManager.class.getMethod("isAppCloneUserPair",
+                    return true;
+                }
+                Method isAppCloneUserPair = StorageManager.class.getMethod("isAppCloneUserPair",
                     int.class, int.class);
-            return (Boolean) isAppCloneUserPair.invoke(mStorageManager, userId1, userId2);
+                return (Boolean) isAppCloneUserPair.invoke(mStorageManager, userId1, userId2);
+            } else {
+                return (mUserCache.userSharesMediaWithParent(user1)
+                    || mUserCache.userSharesMediaWithParent(user2));
+            }
         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
             Log.w(TAG, "isAppCloneUserPair failed. Users: " + userId1 + " and " + userId2);
             return false;
diff --git a/src/com/android/providers/media/TranscodeHelper.java b/src/com/android/providers/media/TranscodeHelper.java
index 19efa8d..c500bf6 100644
--- a/src/com/android/providers/media/TranscodeHelper.java
+++ b/src/com/android/providers/media/TranscodeHelper.java
@@ -221,7 +221,6 @@
     private final MediaProvider mMediaProvider;
     private final PackageManager mPackageManager;
     private final StorageManager mStorageManager;
-    private final MediaTranscodeManager mMediaTranscodeManager;
     private final ActivityManager mActivityManager;
     private final File mTranscodeDirectory;
     @GuardedBy("mLock")
@@ -262,7 +261,6 @@
         mContext = context;
         mPackageManager = context.getPackageManager();
         mStorageManager = context.getSystemService(StorageManager.class);
-        mMediaTranscodeManager = context.getSystemService(MediaTranscodeManager.class);
         mActivityManager = context.getSystemService(ActivityManager.class);
         mMediaProvider = mediaProvider;
         mTranscodeDirectory = new File("/storage/emulated/" + UserHandle.myUserId(),
@@ -1121,6 +1119,9 @@
 
     private TranscodingSession enqueueTranscodingSession(String src, String dst, int uid,
             final CountDownLatch latch) throws UnsupportedOperationException, IOException {
+        // Fetch the service lazily to improve memory usage
+        final MediaTranscodeManager mediaTranscodeManager =
+                mContext.getSystemService(MediaTranscodeManager.class);
         File file = new File(src);
         File transcodeFile = new File(dst);
 
@@ -1144,7 +1145,7 @@
                         .setSourceFileDescriptor(srcPfd)
                         .setDestinationFileDescriptor(dstPfd)
                         .build();
-        TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
+        TranscodingSession session = mediaTranscodeManager.enqueueRequest(request,
                 ForegroundThread.getExecutor(),
                 s -> {
                     mTranscodingUiNotifier.stop(s, src);
diff --git a/src/com/android/providers/media/util/UserCache.java b/src/com/android/providers/media/util/UserCache.java
index 6d5e623..38d5326 100644
--- a/src/com/android/providers/media/util/UserCache.java
+++ b/src/com/android/providers/media/util/UserCache.java
@@ -26,6 +26,8 @@
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 
+import com.android.modules.utils.build.SdkLevel;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -64,6 +66,10 @@
             mUsers.clear();
             // Add the user we're running as by default
             mUsers.add(Process.myUserHandle());
+            if (!SdkLevel.isAtLeastS()) {
+                // Before S, we only handle the owner user
+                return;
+            }
             // And find all profiles that share media with us
             for (UserHandle profile : profiles) {
                 if (!profile.equals(mContext.getUser())) {
diff --git a/tests/src/com/android/providers/media/scan/ModernMediaScannerTest.java b/tests/src/com/android/providers/media/scan/ModernMediaScannerTest.java
index cc355d0..cc570b3 100644
--- a/tests/src/com/android/providers/media/scan/ModernMediaScannerTest.java
+++ b/tests/src/com/android/providers/media/scan/ModernMediaScannerTest.java
@@ -1218,6 +1218,7 @@
         File renamedTestDir = new File(mIsolatedContext.getExternalMediaDirs()[0],
                 "renamed_test_" + System.nanoTime());
         assertThat(mDir.renameTo(renamedTestDir)).isTrue();
+        MediaStore.waitForIdle(mIsolatedResolver);
 
         Timer renamedDirScan = new Timer("renamedDirScan");
         renamedDirScan.start();