Merge "Lazily fetch the MediaTranscodeManager service" 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/tests/Android.bp b/tests/Android.bp
index 0cf1a3b..8a0503d 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1,4 +1,23 @@
 android_test_helper_app {
+    name: "MediaProviderTestAppForPermissionActivity",
+    manifest: "test_app/TestAppForPermissionActivity.xml",
+    srcs: [
+        "test_app/src/**/*.java",
+        "src/com/android/providers/media/util/TestUtils.java",
+    ],
+    static_libs: [
+        "cts-install-lib",
+    ],
+    sdk_version: "test_current",
+    target_sdk_version: "30",
+    min_sdk_version: "30",
+    test_suites: [
+        "device-tests",
+        "mts-mediaprovider",
+    ],
+}
+
+android_test_helper_app {
     name: "MediaProviderTestAppWithStoragePerms",
     manifest: "test_app/TestAppWithStoragePerms.xml",
     srcs: [
@@ -123,6 +142,7 @@
     java_resources: [
         ":MediaProviderTestAppWithStoragePerms",
         ":MediaProviderTestAppWithoutPerms",
+        ":MediaProviderTestAppForPermissionActivity",
         ":LegacyMediaProviderTestApp",
     ],
 
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index 6b929cf..1cae732 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -16,6 +16,7 @@
 <configuration description="Runs Tests for MediaProvder.">
     <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
         <option name="test-file-name" value="MediaProviderTests.apk" />
+        <option name="test-file-name" value="MediaProviderTestAppForPermissionActivity.apk" />
         <option name="test-file-name" value="MediaProviderTestAppWithStoragePerms.apk" />
         <option name="test-file-name" value="MediaProviderTestAppWithoutPerms.apk" />
         <option name="test-file-name" value="LegacyMediaProviderTestApp.apk" />
diff --git a/tests/src/com/android/providers/media/PermissionActivityTest.java b/tests/src/com/android/providers/media/PermissionActivityTest.java
index e019d65..f2e44e3 100644
--- a/tests/src/com/android/providers/media/PermissionActivityTest.java
+++ b/tests/src/com/android/providers/media/PermissionActivityTest.java
@@ -65,7 +65,7 @@
 @RunWith(AndroidJUnit4.class)
 public class PermissionActivityTest {
     private static final String TEST_APP_PACKAGE_NAME =
-            "com.android.providers.media.testapp.withstorageperms";
+            "com.android.providers.media.testapp.permission";
 
     private static final int TEST_APP_PID = -1;
     private int mTestAppUid = -1;
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();
diff --git a/tests/test_app/TestAppForPermissionActivity.xml b/tests/test_app/TestAppForPermissionActivity.xml
new file mode 100644
index 0000000..cd1cc82
--- /dev/null
+++ b/tests/test_app/TestAppForPermissionActivity.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.providers.media.testapp.permission"
+          android:versionCode="1"
+          android:versionName="1.0">
+
+    <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+
+    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.MANAGE_MEDIA"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+    <application android:label="TestAppPerms">
+        <activity android:name="com.android.providers.media.util.TestAppActivity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file