Merge "Add MTS suite config" into mainline-prod
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 305027b..4fe4843 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,6 +25,9 @@
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
+ <!-- Permissions required for statsd pull metrics -->
+ <uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM"/>
+
<application
android:name="com.android.providers.media.MediaApplication"
android:label="@string/app_label"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 93218cf..3af81a2 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -31,6 +31,9 @@
"name": "CtsScopedStorageHostTest"
},
{
+ "name": "CtsScopedStorageDeviceOnlyTest"
+ },
+ {
"name": "fuse_node_test"
}
],
diff --git a/jni/MediaProviderWrapper.cpp b/jni/MediaProviderWrapper.cpp
index fb72961..734ae97 100644
--- a/jni/MediaProviderWrapper.cpp
+++ b/jni/MediaProviderWrapper.cpp
@@ -116,13 +116,6 @@
return res;
}
-void scanFileInternal(JNIEnv* env, jobject media_provider_object, jmethodID mid_scan_file,
- const string& path) {
- ScopedLocalRef<jstring> j_path(env, env->NewStringUTF(path.c_str()));
- env->CallVoidMethod(media_provider_object, mid_scan_file, j_path.get());
- CheckForJniException(env);
-}
-
int isMkdirOrRmdirAllowedInternal(JNIEnv* env, jobject media_provider_object,
jmethodID mid_is_mkdir_or_rmdir_allowed, const string& path,
uid_t uid, bool forCreate) {
@@ -267,8 +260,6 @@
mid_delete_file_ = CacheMethod(env, "deleteFile", "(Ljava/lang/String;I)I", /*is_static*/ false);
mid_is_open_allowed_ = CacheMethod(env, "isOpenAllowed", "(Ljava/lang/String;IZ)I",
/*is_static*/ false);
- mid_scan_file_ = CacheMethod(env, "scanFile", "(Ljava/lang/String;)V",
- /*is_static*/ false);
mid_is_mkdir_or_rmdir_allowed_ = CacheMethod(env, "isDirectoryCreationOrDeletionAllowed",
"(Ljava/lang/String;IZ)I", /*is_static*/ false);
mid_is_opendir_allowed_ = CacheMethod(env, "isOpendirAllowed", "(Ljava/lang/String;IZ)I",
@@ -341,11 +332,6 @@
for_write);
}
-void MediaProviderWrapper::ScanFile(const string& path) {
- JNIEnv* env = MaybeAttachCurrentThread();
- scanFileInternal(env, media_provider_object_, mid_scan_file_, path);
-}
-
int MediaProviderWrapper::IsCreatingDirAllowed(const string& path, uid_t uid) {
if (shouldBypassMediaProvider(uid)) {
return 0;
diff --git a/jni/MediaProviderWrapper.h b/jni/MediaProviderWrapper.h
index ce5a5b1..23c611a 100644
--- a/jni/MediaProviderWrapper.h
+++ b/jni/MediaProviderWrapper.h
@@ -101,18 +101,6 @@
int IsOpenAllowed(const std::string& path, uid_t uid, bool for_write);
/**
- * Potentially triggers a scan of the file before closing it and reconciles it with the
- * MediaProvider database.
- *
- * @param path the path of the file to be scanned
- */
- void ScanFile(const std::string& path);
-
- /**
- * Determines if the given UID is allowed to create a directory with the given path.
- *
- * @param path the path of the directory to be created
- * @param uid UID of the calling app
* @return 0 if it's allowed, or errno error code if operation isn't allowed.
*/
int IsCreatingDirAllowed(const std::string& path, uid_t uid);
@@ -202,7 +190,6 @@
jmethodID mid_insert_file_;
jmethodID mid_delete_file_;
jmethodID mid_is_open_allowed_;
- jmethodID mid_scan_file_;
jmethodID mid_is_mkdir_or_rmdir_allowed_;
jmethodID mid_is_opendir_allowed_;
jmethodID mid_get_files_in_dir_;
diff --git a/src/com/android/providers/media/DatabaseHelper.java b/src/com/android/providers/media/DatabaseHelper.java
index faa6d18..9c67aa6 100644
--- a/src/com/android/providers/media/DatabaseHelper.java
+++ b/src/com/android/providers/media/DatabaseHelper.java
@@ -876,9 +876,17 @@
final String data = c.getString(c.getColumnIndex(MediaColumns.DATA));
values.put(MediaColumns.DATA, data);
FileUtils.computeValuesFromData(values, /*isForFuse*/ false);
+ final String volumeNameFromPath = values.getAsString(MediaColumns.VOLUME_NAME);
for (String column : sMigrateColumns) {
DatabaseUtils.copyFromCursorToContentValues(column, c, values);
}
+ final String volumeNameMigrated = values.getAsString(MediaColumns.VOLUME_NAME);
+ // While upgrading from P OS or below, VOLUME_NAME can be NULL in legacy
+ // database. When VOLUME_NAME is NULL, extract VOLUME_NAME from
+ // MediaColumns.DATA
+ if (volumeNameMigrated == null || volumeNameMigrated.isEmpty()) {
+ values.put(MediaColumns.VOLUME_NAME, volumeNameFromPath);
+ }
final String volumePath = FileUtils.extractVolumePath(data);
@@ -905,7 +913,7 @@
} catch (Exception e) {
// We only have one shot to migrate data, so log and
// keep marching forward.
- Log.wtf(TAG, "Couldn't migrate playlist file " + data);
+ Log.w(TAG, "Couldn't migrate playlist file " + data);
}
values.put(FileColumns.DATA, playlistFilePath);
@@ -926,7 +934,7 @@
} catch (IOException e) {
// We only have one shot to migrate data, so log and
// keep marching forward
- Log.wtf(TAG, "Failed to rename " + values + "; continuing", e);
+ Log.w(TAG, "Failed to rename " + values + "; continuing", e);
FileUtils.computeValuesFromData(values, /*isForFuse*/ false);
}
}
@@ -957,7 +965,7 @@
} catch (Exception e) {
// We have to guard ourselves against any weird behavior of the
// legacy provider by trying to catch everything
- Log.wtf(TAG, "Failed migration from legacy provider", e);
+ Log.w(TAG, "Failed migration from legacy provider", e);
}
// We tried our best above to migrate everything we could, and we
@@ -1076,7 +1084,7 @@
} catch (IOException e) {
// We only have one shot to migrate data, so log and
// keep marching forward.
- Log.wtf(TAG, "Couldn't migrate playlist file " + playlistFile);
+ Log.w(TAG, "Couldn't migrate playlist file " + playlistFile);
}
} catch (RemoteException e) {
throw new IllegalStateException(e);
@@ -1092,7 +1100,7 @@
return c.getString(0);
}
} catch (Exception e) {
- Log.wtf(TAG, "Exception occurred while querying for data file for " + uri, e);
+ Log.w(TAG, "Exception occurred while querying for data file for " + uri, e);
}
return null;
}
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 4166234..9e1efa5 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -1220,17 +1220,6 @@
}
/**
- * Makes MediaScanner scan the given file.
- * @param file path of the file to be scanned
- *
- * Called from JNI in jni/MediaProviderWrapper.cpp
- */
- @Keep
- public void scanFileForFuse(String file) {
- scanFile(new File(file), REASON_DEMAND);
- }
-
- /**
* Called when a new file is created through FUSE
*
* @param file path of the file that was created
@@ -1756,13 +1745,8 @@
* </ul>
*/
private void scanRenamedDirectoryForFuse(@NonNull String oldPath, @NonNull String newPath) {
- final LocalCallingIdentity token = clearLocalCallingIdentity();
- try {
- scanFile(new File(oldPath), REASON_DEMAND);
- scanFile(new File(newPath), REASON_DEMAND);
- } finally {
- restoreLocalCallingIdentity(token);
- }
+ scanFileAsMediaProvider(new File(oldPath), REASON_DEMAND);
+ scanFileAsMediaProvider(new File(newPath), REASON_DEMAND);
}
/**
@@ -2213,10 +2197,10 @@
// 3) /sdcard/foo/bar.mp3 => /sdcard/foo/.nomedia
// in this case, we need to scan all of /sdcard/foo
if (extractDisplayName(oldPath).equals(".nomedia")) {
- scanFile(new File(oldPath).getParentFile(), REASON_DEMAND);
+ scanFileAsMediaProvider(new File(oldPath).getParentFile(), REASON_DEMAND);
}
if (extractDisplayName(newPath).equals(".nomedia")) {
- scanFile(new File(newPath).getParentFile(), REASON_DEMAND);
+ scanFileAsMediaProvider(new File(newPath).getParentFile(), REASON_DEMAND);
}
return 0;
@@ -3891,7 +3875,7 @@
mCallingIdentity.get().setOwned(rowId, true);
if (path != null && path.toLowerCase(Locale.ROOT).endsWith("/.nomedia")) {
- mMediaScanner.scanFile(new File(path).getParentFile(), REASON_DEMAND);
+ scanFileAsMediaProvider(new File(path).getParentFile(), REASON_DEMAND);
}
return newUri;
@@ -4788,8 +4772,10 @@
// Do this on a background thread, since we don't want to make binder
// calls as part of a FUSE call.
helper.postBackground(() -> {
- getContext().getSystemService(DownloadManager.class)
- .onMediaStoreDownloadsDeleted(deletedDownloadIds);
+ DownloadManager dm = getContext().getSystemService(DownloadManager.class);
+ if (dm != null) {
+ dm.onMediaStoreDownloadsDeleted(deletedDownloadIds);
+ }
});
}
@@ -6595,7 +6581,7 @@
update(uri, values, null, null);
break;
default:
- mMediaScanner.scanFile(file, REASON_DEMAND);
+ scanFileAsMediaProvider(file, REASON_DEMAND);
break;
}
} catch (Exception e2) {
diff --git a/src/com/android/providers/media/PermissionActivity.java b/src/com/android/providers/media/PermissionActivity.java
index 0183690..23c3f90 100644
--- a/src/com/android/providers/media/PermissionActivity.java
+++ b/src/com/android/providers/media/PermissionActivity.java
@@ -189,17 +189,6 @@
actionDialog = builder.show();
- // The title is being set as a message above.
- // We need to style it like the default AlertDialog title
- TextView dialogMessage = (TextView) actionDialog.findViewById(
- android.R.id.message);
- if (dialogMessage != null) {
- dialogMessage.setTextAppearance(
- android.R.style.TextAppearance_DeviceDefault_DialogWindowTitle);
- } else {
- Log.w(TAG, "Couldn't find message element");
- }
-
final WindowManager.LayoutParams params = actionDialog.getWindow().getAttributes();
params.width = getResources().getDimensionPixelSize(R.dimen.permission_dialog_width);
actionDialog.getWindow().setAttributes(params);
diff --git a/src/com/android/providers/media/util/IsoInterface.java b/src/com/android/providers/media/util/IsoInterface.java
index 5de4b6b..03b46c9 100644
--- a/src/com/android/providers/media/util/IsoInterface.java
+++ b/src/com/android/providers/media/util/IsoInterface.java
@@ -177,14 +177,25 @@
return null;
}
- box.data = new byte[(int) (len - box.headerSize)];
+ try {
+ box.data = new byte[(int) (len - box.headerSize)];
+ } catch (OutOfMemoryError e) {
+ Log.w(TAG, "Couldn't read large uuid box", e);
+ return null;
+ }
Os.read(fd, box.data, 0, box.data.length);
} else if (type == BOX_XMP) {
if (len > Integer.MAX_VALUE) {
Log.w(TAG, "Skipping abnormally large xmp box");
return null;
}
- box.data = new byte[(int) (len - box.headerSize)];
+
+ try {
+ box.data = new byte[(int) (len - box.headerSize)];
+ } catch (OutOfMemoryError e) {
+ Log.w(TAG, "Couldn't read large xmp box", e);
+ return null;
+ }
Os.read(fd, box.data, 0, box.data.length);
} else if (type == BOX_META && len != headerSize) {
// The format of this differs in ISO and QT encoding:
diff --git a/tests/client/src/com/android/providers/media/client/LegacyProviderMigrationTest.java b/tests/client/src/com/android/providers/media/client/LegacyProviderMigrationTest.java
index 8014b35..831aa9b 100644
--- a/tests/client/src/com/android/providers/media/client/LegacyProviderMigrationTest.java
+++ b/tests/client/src/com/android/providers/media/client/LegacyProviderMigrationTest.java
@@ -207,6 +207,18 @@
doLegacy(mExternalDownloads, values);
}
+ /**
+ * Test that migrating from legacy database with volume_name=NULL doesn't
+ * result in empty cursor when queried.
+ */
+ @Test
+ public void testMigrateNullVolumeName() throws Exception {
+ final ContentValues values = generateValues(FileColumns.MEDIA_TYPE_IMAGE,
+ "image/png", Environment.DIRECTORY_PICTURES);
+ values.remove(MediaColumns.VOLUME_NAME);
+ doLegacy(mExternalImages, values);
+ }
+
@Test
public void testLegacy_PlaylistMap() throws Exception {
final Context context = InstrumentationRegistry.getTargetContext();
diff --git a/tests/src/com/android/providers/media/MediaProviderForFuseTest.java b/tests/src/com/android/providers/media/MediaProviderForFuseTest.java
index 277acf2..e4d2e52 100644
--- a/tests/src/com/android/providers/media/MediaProviderForFuseTest.java
+++ b/tests/src/com/android/providers/media/MediaProviderForFuseTest.java
@@ -138,13 +138,6 @@
}
@Test
- public void test_scanFileForFuse() throws Exception {
- final File file = new File(sTestDir, "test" + System.nanoTime() + ".jpg");
- Truth.assertThat(file.createNewFile()).isTrue();
- sMediaProvider.scanFileForFuse(file.getPath());
- }
-
- @Test
public void test_isOpendirAllowedForFuse() throws Exception {
Truth.assertThat(sMediaProvider.isOpendirAllowedForFuse(
sTestDir.getPath(), sTestUid, /* forWrite */ false)).isEqualTo(0);