summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-11 21:09:55 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-11 21:09:55 +0000
commita4979cde29a16b6e513f1838320f47a40851a524 (patch)
treecf42355f715644f517a5c829f710a879ef0d1078
parent2ba7ca9cc7f6c3256d6068592145b44f109ec95f (diff)
parent2ddae5b1a1167f44e9bc98b5a12f466c8119cf02 (diff)
downloadMediaProvider-android12-platform-release.tar.gz
Change-Id: I1f57582bae4625e54d7061d7653a2abba91ebe45
-rw-r--r--src/com/android/providers/media/MediaProvider.java54
-rw-r--r--src/com/android/providers/media/scan/ModernMediaScanner.java33
-rw-r--r--src/com/android/providers/media/util/FileUtils.java47
3 files changed, 96 insertions, 38 deletions
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 705d7ecc1..31bdf893f 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -5549,38 +5549,48 @@ public class MediaProvider extends ContentProvider {
BackgroundThread.waitForIdle();
return null;
}
- case MediaStore.SCAN_FILE_CALL:
- case MediaStore.SCAN_VOLUME_CALL: {
- final int userId = Binder.getCallingUid() / PER_USER_RANGE;
+ case MediaStore.SCAN_FILE_CALL: {
final LocalCallingIdentity token = clearLocalCallingIdentity();
final CallingIdentity providerToken = clearCallingIdentity();
+
+ final String filePath = arg;
+ final Uri uri;
try {
- final Bundle res = new Bundle();
- switch (method) {
- case MediaStore.SCAN_FILE_CALL: {
- final File file = new File(arg);
- res.putParcelable(Intent.EXTRA_STREAM, scanFile(file, REASON_DEMAND));
- break;
- }
- case MediaStore.SCAN_VOLUME_CALL: {
- final String volumeName = arg;
- try {
- MediaVolume volume = mVolumeCache.findVolume(volumeName,
- UserHandle.of(userId));
- MediaService.onScanVolume(getContext(), volume, REASON_DEMAND);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Failed to find volume " + volumeName, e);
- }
- break;
- }
+ File file;
+ try {
+ file = FileUtils.getCanonicalFile(filePath);
+ } catch (IOException e) {
+ file = null;
}
- return res;
+
+ uri = file != null ? scanFile(file, REASON_DEMAND) : null;
+ } finally {
+ restoreCallingIdentity(providerToken);
+ restoreLocalCallingIdentity(token);
+ }
+
+ final Bundle res = new Bundle();
+ res.putParcelable(Intent.EXTRA_STREAM, uri);
+ return res;
+ }
+ case MediaStore.SCAN_VOLUME_CALL: {
+ final UserHandle user = UserHandle.of(Binder.getCallingUid() / PER_USER_RANGE);
+ final LocalCallingIdentity token = clearLocalCallingIdentity();
+ final CallingIdentity providerToken = clearCallingIdentity();
+
+ final String volumeName = arg;
+ try {
+ final MediaVolume volume = mVolumeCache.findVolume(volumeName, user);
+ MediaService.onScanVolume(getContext(), volume, REASON_DEMAND);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Failed to find volume " + volumeName, e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
restoreCallingIdentity(providerToken);
restoreLocalCallingIdentity(token);
}
+ return Bundle.EMPTY;
}
case MediaStore.GET_VERSION_CALL: {
final String volumeName = extras.getString(Intent.EXTRA_TEXT);
diff --git a/src/com/android/providers/media/scan/ModernMediaScanner.java b/src/com/android/providers/media/scan/ModernMediaScanner.java
index 8927bfa56..5087c19ad 100644
--- a/src/com/android/providers/media/scan/ModernMediaScanner.java
+++ b/src/com/android/providers/media/scan/ModernMediaScanner.java
@@ -50,6 +50,8 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static com.android.providers.media.util.Metrics.translateReason;
+import static java.util.Objects.requireNonNull;
+
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -243,7 +245,15 @@ public class ModernMediaScanner implements MediaScanner {
}
@Override
- public void scanDirectory(File file, int reason) {
+ public void scanDirectory(@NonNull File file, int reason) {
+ requireNonNull(file);
+ try {
+ file = file.getCanonicalFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Couldn't canonicalize directory to scan" + file, e);
+ return;
+ }
+
try (Scan scan = new Scan(file, reason, /*ownerPackage*/ null)) {
scan.run();
} catch (OperationCanceledException ignored) {
@@ -253,12 +263,21 @@ public class ModernMediaScanner implements MediaScanner {
}
@Override
- public Uri scanFile(File file, int reason) {
+ @Nullable
+ public Uri scanFile(@NonNull File file, int reason) {
return scanFile(file, reason, /*ownerPackage*/ null);
}
@Override
public Uri scanFile(File file, int reason, @Nullable String ownerPackage) {
+ requireNonNull(file);
+ try {
+ file = file.getCanonicalFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Couldn't canonicalize file to scan" + file, e);
+ return null;
+ }
+
try (Scan scan = new Scan(file, reason, ownerPackage)) {
scan.run();
return scan.getFirstResult();
@@ -294,9 +313,17 @@ public class ModernMediaScanner implements MediaScanner {
@Override
public void onDirectoryDirty(File dir) {
+ requireNonNull(dir);
+ try {
+ dir = dir.getCanonicalFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Couldn't canonicalize directory" + dir, e);
+ return;
+ }
+
synchronized (mPendingCleanDirectories) {
mPendingCleanDirectories.remove(dir.getPath());
- FileUtils.setDirectoryDirty(dir, /*isDirty*/ true);
+ FileUtils.setDirectoryDirty(dir, /* isDirty */ true);
}
}
diff --git a/src/com/android/providers/media/util/FileUtils.java b/src/com/android/providers/media/util/FileUtils.java
index a0f666fbd..e5c62d160 100644
--- a/src/com/android/providers/media/util/FileUtils.java
+++ b/src/com/android/providers/media/util/FileUtils.java
@@ -1101,18 +1101,25 @@ public class FileUtils {
}
public static @Nullable String extractRelativePath(@Nullable String data) {
- data = getCanonicalPath(data);
if (data == null) return null;
- final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(data);
+ final String path;
+ try {
+ path = getCanonicalPath(data);
+ } catch (IOException e) {
+ Log.d(TAG, "Unable to get canonical path from invalid data path: " + data, e);
+ return null;
+ }
+
+ final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(path);
if (matcher.find()) {
- final int lastSlash = data.lastIndexOf('/');
+ final int lastSlash = path.lastIndexOf('/');
if (lastSlash == -1 || lastSlash < matcher.end()) {
// This is a file in the top-level directory, so relative path is "/"
// which is different than null, which means unknown path
return "/";
} else {
- return data.substring(matcher.end(), lastSlash + 1);
+ return path.substring(matcher.end(), lastSlash + 1);
}
} else {
return null;
@@ -1667,15 +1674,29 @@ public class FileUtils {
return null;
}
- @Nullable
- private static String getCanonicalPath(@Nullable String path) {
- if (path == null) return null;
+ /**
+ * Returns the canonical {@link File} for the provided abstract pathname.
+ *
+ * @return The canonical pathname string denoting the same file or directory as this abstract
+ * pathname
+ * @see File#getCanonicalFile()
+ */
+ @NonNull
+ public static File getCanonicalFile(@NonNull String path) throws IOException {
+ Objects.requireNonNull(path);
+ return new File(path).getCanonicalFile();
+ }
- try {
- return new File(path).getCanonicalPath();
- } catch (IOException e) {
- Log.d(TAG, "Unable to get canonical path from invalid data path: " + path, e);
- return null;
- }
+ /**
+ * Returns the canonical pathname string of the provided abstract pathname.
+ *
+ * @return The canonical pathname string denoting the same file or directory as this abstract
+ * pathname.
+ * @see File#getCanonicalPath()
+ */
+ @NonNull
+ public static String getCanonicalPath(@NonNull String path) throws IOException {
+ Objects.requireNonNull(path);
+ return new File(path).getCanonicalPath();
}
}