Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da4cb98b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Fix renaming file and moving file issue in MTP" into rvc-qpr-dev am: d0993213

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13090503

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ibdb009f96a2e55bb29dd7189451a7cbf57d6919a
parents ce98a47a d0993213
Loading
Loading
Loading
Loading
+24 −96
Original line number Diff line number Diff line
@@ -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");
        }