summaryrefslogtreecommitdiff
path: root/media/java/android/mtp/MtpDatabase.java
diff options
context:
space:
mode:
authorIvan Chiang <chiangi@google.com>2020-11-10 10:44:05 +0800
committerIvan Chiang <chiangi@google.com>2021-01-11 10:47:12 +0000
commit23ed52f9716134e5ea7fe9c90bedab29cf90876c (patch)
tree3f86dd186a73c6c763e9263af0f5cca37cfc811b /media/java/android/mtp/MtpDatabase.java
parentb26c104b457e8814f435a8ff3041cae54d6995b4 (diff)
Fix renaming file and moving file issue in MTP
After the user renames/moves a file/directory, the database of MediaProvider is not updated. It causes that the file can't be opened via MediaProvider. Use scanFile to instead of MP.update for the file/directory. Handle the .nomedia case for create/copy/move/delete/rename. Scan the parent directory to update the database. Test: atest MtpTests Test: atest --test-mapping packages/providers/MediaProvider Test: manual. 1. Move/rename the file/directory. 2. Open the file in DocumentsUI 3. create/copy/move/delete/rename for .nomedia case Bug: 169300366 Bug: 171538933 Bug: 172029805 Bug: 170798581 Change-Id: Ia37be7a027bfe502e3f7c96babe5a5bbed5f942c Merged-In: Ia37be7a027bfe502e3f7c96babe5a5bbed5f942c (cherry picked from commit 20079f10644e641bbb2c35c250e8a9e0b9f6c1b3)
Diffstat (limited to 'media/java/android/mtp/MtpDatabase.java')
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java120
1 files changed, 24 insertions, 96 deletions
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index ed56b4398c22..798bf6e2f8ee 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -19,8 +19,7 @@ package android.mtp;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ContentProviderClient;
-import android.content.ContentUris;
-import android.content.ContentValues;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -32,7 +31,6 @@ import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.BatteryManager;
-import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
@@ -103,8 +101,6 @@ public class MtpDatabase implements AutoCloseable {
private MtpStorageManager mManager;
private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
- private static final String[] ID_PROJECTION = new String[] {Files.FileColumns._ID};
- private static final String[] PATH_PROJECTION = new String[] {Files.FileColumns.DATA};
private static final String NO_MEDIA = ".nomedia";
static {
@@ -431,7 +427,7 @@ public class MtpDatabase implements AutoCloseable {
}
// Add the new file to MediaProvider
if (succeeded) {
- MediaStore.scanFile(mContext.getContentResolver(), obj.getPath().toFile());
+ updateMediaStore(mContext, obj.getPath().toFile());
}
}
@@ -580,32 +576,8 @@ public class MtpDatabase implements AutoCloseable {
return MtpConstants.RESPONSE_GENERAL_ERROR;
}
- // finally update MediaProvider
- ContentValues values = new ContentValues();
- values.put(Files.FileColumns.DATA, newPath.toString());
- String[] whereArgs = new String[]{oldPath.toString()};
- try {
- // note - we are relying on a special case in MediaProvider.update() to update
- // the paths for all children in the case where this is a directory.
- final Uri objectsUri = MediaStore.Files.getContentUri(obj.getVolumeName());
- mMediaProvider.update(objectsUri, values, PATH_WHERE, whereArgs);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in mMediaProvider.update", e);
- }
-
- // check if nomedia status changed
- if (obj.isDir()) {
- // for directories, check if renamed from something hidden to something non-hidden
- if (oldPath.getFileName().startsWith(".") && !newPath.startsWith(".")) {
- MediaStore.scanFile(mContext.getContentResolver(), newPath.toFile());
- }
- } else {
- // for files, check if renamed from .nomedia to something else
- if (oldPath.getFileName().toString().toLowerCase(Locale.US).equals(NO_MEDIA)
- && !newPath.getFileName().toString().toLowerCase(Locale.US).equals(NO_MEDIA)) {
- MediaStore.scanFile(mContext.getContentResolver(), newPath.getParent().toFile());
- }
- }
+ updateMediaStore(mContext, oldPath.toFile());
+ updateMediaStore(mContext, newPath.toFile());
return MtpConstants.RESPONSE_OK;
}
@@ -635,48 +607,15 @@ public class MtpDatabase implements AutoCloseable {
Log.e(TAG, "Failed to end move object");
return;
}
-
obj = mManager.getObject(objId);
if (!success || obj == null)
return;
- // Get parent info from MediaProvider, since the id is different from MTP's
- ContentValues values = new ContentValues();
+
Path path = newParentObj.getPath().resolve(name);
Path oldPath = oldParentObj.getPath().resolve(name);
- values.put(Files.FileColumns.DATA, path.toString());
- if (obj.getParent().isRoot()) {
- values.put(Files.FileColumns.PARENT, 0);
- } else {
- int parentId = findInMedia(newParentObj, path.getParent());
- if (parentId != -1) {
- values.put(Files.FileColumns.PARENT, parentId);
- } else {
- // The new parent isn't in MediaProvider, so delete the object instead
- deleteFromMedia(obj, oldPath, obj.isDir());
- return;
- }
- }
- // update MediaProvider
- Cursor c = null;
- String[] whereArgs = new String[]{oldPath.toString()};
- try {
- int parentId = -1;
- if (!oldParentObj.isRoot()) {
- parentId = findInMedia(oldParentObj, oldPath.getParent());
- }
- if (oldParentObj.isRoot() || parentId != -1) {
- // Old parent exists in MediaProvider - perform a move
- // note - we are relying on a special case in MediaProvider.update() to update
- // the paths for all children in the case where this is a directory.
- final Uri objectsUri = MediaStore.Files.getContentUri(obj.getVolumeName());
- mMediaProvider.update(objectsUri, values, PATH_WHERE, whereArgs);
- } else {
- // Old parent doesn't exist - add the object
- MediaStore.scanFile(mContext.getContentResolver(), path.toFile());
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in mMediaProvider.update", e);
- }
+
+ updateMediaStore(mContext, oldPath.toFile());
+ updateMediaStore(mContext, path.toFile());
}
@VisibleForNative
@@ -699,7 +638,19 @@ public class MtpDatabase implements AutoCloseable {
if (!success) {
return;
}
- MediaStore.scanFile(mContext.getContentResolver(), obj.getPath().toFile());
+
+ updateMediaStore(mContext, obj.getPath().toFile());
+ }
+
+ private static void updateMediaStore(@NonNull Context context, @NonNull File file) {
+ final ContentResolver resolver = context.getContentResolver();
+ // For file, check whether the file name is .nomedia or not.
+ // If yes, scan the parent directory to update all files in the directory.
+ if (!file.isDirectory() && file.getName().toLowerCase(Locale.ROOT).endsWith(NO_MEDIA)) {
+ MediaStore.scanFile(resolver, file.getParentFile());
+ } else {
+ MediaStore.scanFile(resolver, file);
+ }
}
@VisibleForNative
@@ -928,26 +879,6 @@ public class MtpDatabase implements AutoCloseable {
deleteFromMedia(obj, obj.getPath(), obj.isDir());
}
- private int findInMedia(MtpStorageManager.MtpObject obj, Path path) {
- final Uri objectsUri = MediaStore.Files.getContentUri(obj.getVolumeName());
-
- int ret = -1;
- Cursor c = null;
- try {
- c = mMediaProvider.query(objectsUri, ID_PROJECTION, PATH_WHERE,
- new String[]{path.toString()}, null, null);
- if (c != null && c.moveToNext()) {
- ret = c.getInt(0);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error finding " + path + " in MediaProvider");
- } finally {
- if (c != null)
- c.close();
- }
- return ret;
- }
-
private void deleteFromMedia(MtpStorageManager.MtpObject obj, Path path, boolean isDir) {
final Uri objectsUri = MediaStore.Files.getContentUri(obj.getVolumeName());
try {
@@ -963,13 +894,10 @@ public class MtpDatabase implements AutoCloseable {
}
String[] whereArgs = new String[]{path.toString()};
- if (mMediaProvider.delete(objectsUri, PATH_WHERE, whereArgs) > 0) {
- if (!isDir && path.toString().toLowerCase(Locale.US).endsWith(NO_MEDIA)) {
- MediaStore.scanFile(mContext.getContentResolver(), path.getParent().toFile());
- }
- } else {
- Log.i(TAG, "Mediaprovider didn't delete " + path);
+ if (mMediaProvider.delete(objectsUri, PATH_WHERE, whereArgs) == 0) {
+ Log.i(TAG, "MediaProvider didn't delete " + path);
}
+ updateMediaStore(mContext, path.toFile());
} catch (Exception e) {
Log.d(TAG, "Failed to delete " + path + " from MediaProvider");
}