/*
 * Copyright (C) 2010 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.
 */

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.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
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;
import android.provider.MediaStore.Files;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForNative;
import com.android.internal.annotations.VisibleForTesting;

import dalvik.system.CloseGuard;

import com.google.android.collect.Sets;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.IntStream;

/**
 * MtpDatabase provides an interface for MTP operations that MtpServer can use. To do this, it uses
 * MtpStorageManager for filesystem operations and MediaProvider to get media metadata. File
 * operations are also reflected in MediaProvider if possible.
 * operations
 * {@hide}
 */
public class MtpDatabase implements AutoCloseable {
    private static final String TAG = MtpDatabase.class.getSimpleName();
    private static final int MAX_THUMB_SIZE = (200 * 1024);

    private final Context mContext;
    private final ContentProviderClient mMediaProvider;

    private final AtomicBoolean mClosed = new AtomicBoolean();
    private final CloseGuard mCloseGuard = CloseGuard.get();

    private final HashMap<String, MtpStorage> mStorageMap = new HashMap<>();

    // cached property groups for single properties
    private final SparseArray<MtpPropertyGroup> mPropertyGroupsByProperty = new SparseArray<>();

    // cached property groups for all properties for a given format
    private final SparseArray<MtpPropertyGroup> mPropertyGroupsByFormat = new SparseArray<>();

    // SharedPreferences for writable MTP device properties
    private SharedPreferences mDeviceProperties;

    // Cached device properties
    private int mBatteryLevel;
    private int mBatteryScale;
    private int mDeviceType;

    private MtpServer mServer;
    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 {
        System.loadLibrary("media_jni");
    }

    private static final int[] PLAYBACK_FORMATS = {
            // allow transferring arbitrary files
            MtpConstants.FORMAT_UNDEFINED,

            MtpConstants.FORMAT_ASSOCIATION,
            MtpConstants.FORMAT_TEXT,
            MtpConstants.FORMAT_HTML,
            MtpConstants.FORMAT_WAV,
            MtpConstants.FORMAT_MP3,
            MtpConstants.FORMAT_MPEG,
            MtpConstants.FORMAT_EXIF_JPEG,
            MtpConstants.FORMAT_TIFF_EP,
            MtpConstants.FORMAT_BMP,
            MtpConstants.FORMAT_GIF,
            MtpConstants.FORMAT_JFIF,
            MtpConstants.FORMAT_PNG,
            MtpConstants.FORMAT_TIFF,
            MtpConstants.FORMAT_WMA,
            MtpConstants.FORMAT_OGG,
            MtpConstants.FORMAT_AAC,
            MtpConstants.FORMAT_MP4_CONTAINER,
            MtpConstants.FORMAT_MP2,
            MtpConstants.FORMAT_3GP_CONTAINER,
            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
            MtpConstants.FORMAT_WPL_PLAYLIST,
            MtpConstants.FORMAT_M3U_PLAYLIST,
            MtpConstants.FORMAT_PLS_PLAYLIST,
            MtpConstants.FORMAT_XML_DOCUMENT,
            MtpConstants.FORMAT_FLAC,
            MtpConstants.FORMAT_DNG,
            MtpConstants.FORMAT_HEIF,
    };

    private static final int[] FILE_PROPERTIES = {
            MtpConstants.PROPERTY_STORAGE_ID,
            MtpConstants.PROPERTY_OBJECT_FORMAT,
            MtpConstants.PROPERTY_PROTECTION_STATUS,
            MtpConstants.PROPERTY_OBJECT_SIZE,
            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
            MtpConstants.PROPERTY_DATE_MODIFIED,
            MtpConstants.PROPERTY_PERSISTENT_UID,
            MtpConstants.PROPERTY_PARENT_OBJECT,
            MtpConstants.PROPERTY_NAME,
            MtpConstants.PROPERTY_DISPLAY_NAME,
            MtpConstants.PROPERTY_DATE_ADDED,
    };

    private static final int[] AUDIO_PROPERTIES = {
            MtpConstants.PROPERTY_ARTIST,
            MtpConstants.PROPERTY_ALBUM_NAME,
            MtpConstants.PROPERTY_ALBUM_ARTIST,
            MtpConstants.PROPERTY_TRACK,
            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
            MtpConstants.PROPERTY_DURATION,
            MtpConstants.PROPERTY_GENRE,
            MtpConstants.PROPERTY_COMPOSER,
            MtpConstants.PROPERTY_AUDIO_WAVE_CODEC,
            MtpConstants.PROPERTY_BITRATE_TYPE,
            MtpConstants.PROPERTY_AUDIO_BITRATE,
            MtpConstants.PROPERTY_NUMBER_OF_CHANNELS,
            MtpConstants.PROPERTY_SAMPLE_RATE,
    };

    private static final int[] VIDEO_PROPERTIES = {
            MtpConstants.PROPERTY_ARTIST,
            MtpConstants.PROPERTY_ALBUM_NAME,
            MtpConstants.PROPERTY_DURATION,
            MtpConstants.PROPERTY_DESCRIPTION,
    };

    private static final int[] IMAGE_PROPERTIES = {
            MtpConstants.PROPERTY_DESCRIPTION,
    };

    private static final int[] DEVICE_PROPERTIES = {
            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
            MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL,
            MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE,
    };

    @VisibleForNative
    private int[] getSupportedObjectProperties(int format) {
        switch (format) {
            case MtpConstants.FORMAT_MP3:
            case MtpConstants.FORMAT_WAV:
            case MtpConstants.FORMAT_WMA:
            case MtpConstants.FORMAT_OGG:
            case MtpConstants.FORMAT_AAC:
                return IntStream.concat(Arrays.stream(FILE_PROPERTIES),
                        Arrays.stream(AUDIO_PROPERTIES)).toArray();
            case MtpConstants.FORMAT_MPEG:
            case MtpConstants.FORMAT_3GP_CONTAINER:
            case MtpConstants.FORMAT_WMV:
                return IntStream.concat(Arrays.stream(FILE_PROPERTIES),
                        Arrays.stream(VIDEO_PROPERTIES)).toArray();
            case MtpConstants.FORMAT_EXIF_JPEG:
            case MtpConstants.FORMAT_GIF:
            case MtpConstants.FORMAT_PNG:
            case MtpConstants.FORMAT_BMP:
            case MtpConstants.FORMAT_DNG:
            case MtpConstants.FORMAT_HEIF:
                return IntStream.concat(Arrays.stream(FILE_PROPERTIES),
                        Arrays.stream(IMAGE_PROPERTIES)).toArray();
            default:
                return FILE_PROPERTIES;
        }
    }

    public static Uri getObjectPropertiesUri(int format, String volumeName) {
        switch (format) {
            case MtpConstants.FORMAT_MP3:
            case MtpConstants.FORMAT_WAV:
            case MtpConstants.FORMAT_WMA:
            case MtpConstants.FORMAT_OGG:
            case MtpConstants.FORMAT_AAC:
                return MediaStore.Audio.Media.getContentUri(volumeName);
            case MtpConstants.FORMAT_MPEG:
            case MtpConstants.FORMAT_3GP_CONTAINER:
            case MtpConstants.FORMAT_WMV:
                return MediaStore.Video.Media.getContentUri(volumeName);
            case MtpConstants.FORMAT_EXIF_JPEG:
            case MtpConstants.FORMAT_GIF:
            case MtpConstants.FORMAT_PNG:
            case MtpConstants.FORMAT_BMP:
            case MtpConstants.FORMAT_DNG:
            case MtpConstants.FORMAT_HEIF:
                return MediaStore.Images.Media.getContentUri(volumeName);
            default:
                return MediaStore.Files.getContentUri(volumeName);
        }
    }

    @VisibleForNative
    private int[] getSupportedDeviceProperties() {
        return DEVICE_PROPERTIES;
    }

    @VisibleForNative
    private int[] getSupportedPlaybackFormats() {
        return PLAYBACK_FORMATS;
    }

    @VisibleForNative
    private int[] getSupportedCaptureFormats() {
        // no capture formats yet
        return null;
    }

    private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                mBatteryScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
                int newLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                if (newLevel != mBatteryLevel) {
                    mBatteryLevel = newLevel;
                    if (mServer != null) {
                        // send device property changed event
                        mServer.sendDevicePropertyChanged(
                                MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL);
                    }
                }
            }
        }
    };

    public MtpDatabase(Context context, String[] subDirectories) {
        native_setup();
        mContext = Objects.requireNonNull(context);
        mMediaProvider = context.getContentResolver()
                .acquireContentProviderClient(MediaStore.AUTHORITY);
        mManager = new MtpStorageManager(new MtpStorageManager.MtpNotifier() {
            @Override
            public void sendObjectAdded(int id) {
                if (MtpDatabase.this.mServer != null)
                    MtpDatabase.this.mServer.sendObjectAdded(id);
            }

            @Override
            public void sendObjectRemoved(int id) {
                if (MtpDatabase.this.mServer != null)
                    MtpDatabase.this.mServer.sendObjectRemoved(id);
            }

            @Override
            public void sendObjectInfoChanged(int id) {
                if (MtpDatabase.this.mServer != null)
                    MtpDatabase.this.mServer.sendObjectInfoChanged(id);
            }
        }, subDirectories == null ? null : Sets.newHashSet(subDirectories));

        initDeviceProperties(context);
        mDeviceType = SystemProperties.getInt("sys.usb.mtp.device_type", 0);
        mCloseGuard.open("close");
    }

    public void setServer(MtpServer server) {
        mServer = server;
        // always unregister before registering
        try {
            mContext.unregisterReceiver(mBatteryReceiver);
        } catch (IllegalArgumentException e) {
            // wasn't previously registered, ignore
        }
        // register for battery notifications when we are connected
        if (server != null) {
            mContext.registerReceiver(mBatteryReceiver,
                    new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        }
    }

    public Context getContext() {
        return mContext;
    }

    @Override
    public void close() {
        mManager.close();
        mCloseGuard.close();
        if (mClosed.compareAndSet(false, true)) {
            if (mMediaProvider != null) {
                mMediaProvider.close();
            }
            native_finalize();
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (mCloseGuard != null) {
                mCloseGuard.warnIfOpen();
            }
            close();
        } finally {
            super.finalize();
        }
    }

    public void addStorage(StorageVolume storage) {
        MtpStorage mtpStorage = mManager.addMtpStorage(storage);
        mStorageMap.put(storage.getPath(), mtpStorage);
        if (mServer != null) {
            mServer.addStorage(mtpStorage);
        }
    }

    public void removeStorage(StorageVolume storage) {
        MtpStorage mtpStorage = mStorageMap.get(storage.getPath());
        if (mtpStorage == null) {
            return;
        }
        if (mServer != null) {
            mServer.removeStorage(mtpStorage);
        }
        mManager.removeMtpStorage(mtpStorage);
        mStorageMap.remove(storage.getPath());
    }

    private void initDeviceProperties(Context context) {
        final String devicePropertiesName = "device-properties";
        mDeviceProperties = context.getSharedPreferences(devicePropertiesName,
                Context.MODE_PRIVATE);
        File databaseFile = context.getDatabasePath(devicePropertiesName);

        if (databaseFile.exists()) {
            // for backward compatibility - read device properties from sqlite database
            // and migrate them to shared prefs
            SQLiteDatabase db = null;
            Cursor c = null;
            try {
                db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
                if (db != null) {
                    c = db.query("properties", new String[]{"_id", "code", "value"},
                            null, null, null, null, null);
                    if (c != null) {
                        SharedPreferences.Editor e = mDeviceProperties.edit();
                        while (c.moveToNext()) {
                            String name = c.getString(1);
                            String value = c.getString(2);
                            e.putString(name, value);
                        }
                        e.commit();
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "failed to migrate device properties", e);
            } finally {
                if (c != null) c.close();
                if (db != null) db.close();
            }
            context.deleteDatabase(devicePropertiesName);
        }
    }

    @VisibleForNative
    @VisibleForTesting
    public int beginSendObject(String path, int format, int parent, int storageId) {
        MtpStorageManager.MtpObject parentObj =
                parent == 0 ? mManager.getStorageRoot(storageId) : mManager.getObject(parent);
        if (parentObj == null) {
            return -1;
        }

        Path objPath = Paths.get(path);
        return mManager.beginSendObject(parentObj, objPath.getFileName().toString(), format);
    }

    @VisibleForNative
    private void endSendObject(int handle, boolean succeeded) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null || !mManager.endSendObject(obj, succeeded)) {
            Log.e(TAG, "Failed to successfully end send object");
            return;
        }
        // Add the new file to MediaProvider
        if (succeeded) {
            MediaStore.scanFile(mContext.getContentResolver(), obj.getPath().toFile());
        }
    }

    @VisibleForNative
    private void rescanFile(String path, int handle, int format) {
        MediaStore.scanFile(mContext.getContentResolver(), new File(path));
    }

    @VisibleForNative
    private int[] getObjectList(int storageID, int format, int parent) {
        List<MtpStorageManager.MtpObject> objs = mManager.getObjects(parent,
                format, storageID);
        if (objs == null) {
            return null;
        }
        int[] ret = new int[objs.size()];
        for (int i = 0; i < objs.size(); i++) {
            ret[i] = objs.get(i).getId();
        }
        return ret;
    }

    @VisibleForNative
    @VisibleForTesting
    public int getNumObjects(int storageID, int format, int parent) {
        List<MtpStorageManager.MtpObject> objs = mManager.getObjects(parent,
                format, storageID);
        if (objs == null) {
            return -1;
        }
        return objs.size();
    }

    @VisibleForNative
    private MtpPropertyList getObjectPropertyList(int handle, int format, int property,
            int groupCode, int depth) {
        // FIXME - implement group support
        if (property == 0) {
            if (groupCode == 0) {
                return new MtpPropertyList(MtpConstants.RESPONSE_PARAMETER_NOT_SUPPORTED);
            }
            return new MtpPropertyList(MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
        }
        if (depth == 0xFFFFFFFF && (handle == 0 || handle == 0xFFFFFFFF)) {
            // request all objects starting at root
            handle = 0xFFFFFFFF;
            depth = 0;
        }
        if (!(depth == 0 || depth == 1)) {
            // we only support depth 0 and 1
            // depth 0: single object, depth 1: immediate children
            return new MtpPropertyList(MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED);
        }
        List<MtpStorageManager.MtpObject> objs = null;
        MtpStorageManager.MtpObject thisObj = null;
        if (handle == 0xFFFFFFFF) {
            // All objects are requested
            objs = mManager.getObjects(0, format, 0xFFFFFFFF);
            if (objs == null) {
                return new MtpPropertyList(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
            }
        } else if (handle != 0) {
            // Add the requested object if format matches
            MtpStorageManager.MtpObject obj = mManager.getObject(handle);
            if (obj == null) {
                return new MtpPropertyList(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
            }
            if (obj.getFormat() == format || format == 0) {
                thisObj = obj;
            }
        }
        if (handle == 0 || depth == 1) {
            if (handle == 0) {
                handle = 0xFFFFFFFF;
            }
            // Get the direct children of root or this object.
            objs = mManager.getObjects(handle, format,
                    0xFFFFFFFF);
            if (objs == null) {
                return new MtpPropertyList(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
            }
        }
        if (objs == null) {
            objs = new ArrayList<>();
        }
        if (thisObj != null) {
            objs.add(thisObj);
        }

        MtpPropertyList ret = new MtpPropertyList(MtpConstants.RESPONSE_OK);
        MtpPropertyGroup propertyGroup;
        for (MtpStorageManager.MtpObject obj : objs) {
            if (property == 0xffffffff) {
                if (format == 0 && handle != 0 && handle != 0xffffffff) {
                    // return properties based on the object's format
                    format = obj.getFormat();
                }
                // Get all properties supported by this object
                // format should be the same between get & put
                propertyGroup = mPropertyGroupsByFormat.get(format);
                if (propertyGroup == null) {
                    final int[] propertyList = getSupportedObjectProperties(format);
                    propertyGroup = new MtpPropertyGroup(propertyList);
                    mPropertyGroupsByFormat.put(format, propertyGroup);
                }
            } else {
                // Get this property value
                propertyGroup = mPropertyGroupsByProperty.get(property);
                if (propertyGroup == null) {
                    final int[] propertyList = new int[]{property};
                    propertyGroup = new MtpPropertyGroup(propertyList);
                    mPropertyGroupsByProperty.put(property, propertyGroup);
                }
            }
            int err = propertyGroup.getPropertyList(mMediaProvider, obj.getVolumeName(), obj, ret);
            if (err != MtpConstants.RESPONSE_OK) {
                return new MtpPropertyList(err);
            }
        }
        return ret;
    }

    private int renameFile(int handle, String newName) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
        }
        Path oldPath = obj.getPath();

        // now rename the file.  make sure this succeeds before updating database
        if (!mManager.beginRenameObject(obj, newName))
            return MtpConstants.RESPONSE_GENERAL_ERROR;
        Path newPath = obj.getPath();
        boolean success = oldPath.toFile().renameTo(newPath.toFile());
        try {
            Os.access(oldPath.toString(), OsConstants.F_OK);
            Os.access(newPath.toString(), OsConstants.F_OK);
        } catch (ErrnoException e) {
            // Ignore. Could fail if the metadata was already updated.
        }

        if (!mManager.endRenameObject(obj, oldPath.getFileName().toString(), success)) {
            Log.e(TAG, "Failed to end rename object");
        }
        if (!success) {
            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());
            }
        }
        return MtpConstants.RESPONSE_OK;
    }

    @VisibleForNative
    private int beginMoveObject(int handle, int newParent, int newStorage) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        MtpStorageManager.MtpObject parent = newParent == 0 ?
                mManager.getStorageRoot(newStorage) : mManager.getObject(newParent);
        if (obj == null || parent == null)
            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;

        boolean allowed = mManager.beginMoveObject(obj, parent);
        return allowed ? MtpConstants.RESPONSE_OK : MtpConstants.RESPONSE_GENERAL_ERROR;
    }

    @VisibleForNative
    private void endMoveObject(int oldParent, int newParent, int oldStorage, int newStorage,
            int objId, boolean success) {
        MtpStorageManager.MtpObject oldParentObj = oldParent == 0 ?
                mManager.getStorageRoot(oldStorage) : mManager.getObject(oldParent);
        MtpStorageManager.MtpObject newParentObj = newParent == 0 ?
                mManager.getStorageRoot(newStorage) : mManager.getObject(newParent);
        MtpStorageManager.MtpObject obj = mManager.getObject(objId);
        String name = obj.getName();
        if (newParentObj == null || oldParentObj == null
                ||!mManager.endMoveObject(oldParentObj, newParentObj, name, success)) {
            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);
        }
    }

    @VisibleForNative
    private int beginCopyObject(int handle, int newParent, int newStorage) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        MtpStorageManager.MtpObject parent = newParent == 0 ?
                mManager.getStorageRoot(newStorage) : mManager.getObject(newParent);
        if (obj == null || parent == null)
            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
        return mManager.beginCopyObject(obj, parent);
    }

    @VisibleForNative
    private void endCopyObject(int handle, boolean success) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null || !mManager.endCopyObject(obj, success)) {
            Log.e(TAG, "Failed to end copy object");
            return;
        }
        if (!success) {
            return;
        }
        MediaStore.scanFile(mContext.getContentResolver(), obj.getPath().toFile());
    }

    @VisibleForNative
    private int setObjectProperty(int handle, int property,
            long intValue, String stringValue) {
        switch (property) {
            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
                return renameFile(handle, stringValue);

            default:
                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
        }
    }

    @VisibleForNative
    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
        switch (property) {
            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
                // writable string properties kept in shared preferences
                String value = mDeviceProperties.getString(Integer.toString(property), "");
                int length = value.length();
                if (length > 255) {
                    length = 255;
                }
                value.getChars(0, length, outStringValue, 0);
                outStringValue[length] = 0;
                return MtpConstants.RESPONSE_OK;
            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
                // use screen size as max image size
                // TODO(b/147721765): Add support for foldables/multi-display devices.
                Display display = ((WindowManager) mContext.getSystemService(
                        Context.WINDOW_SERVICE)).getDefaultDisplay();
                int width = display.getMaximumSizeDimension();
                int height = display.getMaximumSizeDimension();
                String imageSize = Integer.toString(width) + "x" + Integer.toString(height);
                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
                outStringValue[imageSize.length()] = 0;
                return MtpConstants.RESPONSE_OK;
            case MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
                outIntValue[0] = mDeviceType;
                return MtpConstants.RESPONSE_OK;
            case MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL:
                outIntValue[0] = mBatteryLevel;
                outIntValue[1] = mBatteryScale;
                return MtpConstants.RESPONSE_OK;
            default:
                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
        }
    }

    @VisibleForNative
    private int setDeviceProperty(int property, long intValue, String stringValue) {
        switch (property) {
            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
                // writable string properties kept in shared prefs
                SharedPreferences.Editor e = mDeviceProperties.edit();
                e.putString(Integer.toString(property), stringValue);
                return (e.commit() ? MtpConstants.RESPONSE_OK
                        : MtpConstants.RESPONSE_GENERAL_ERROR);
        }

        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
    }

    @VisibleForNative
    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
            char[] outName, long[] outCreatedModified) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return false;
        }
        outStorageFormatParent[0] = obj.getStorageId();
        outStorageFormatParent[1] = obj.getFormat();
        outStorageFormatParent[2] = obj.getParent().isRoot() ? 0 : obj.getParent().getId();

        int nameLen = Integer.min(obj.getName().length(), 255);
        obj.getName().getChars(0, nameLen, outName, 0);
        outName[nameLen] = 0;

        outCreatedModified[0] = obj.getModifiedTime();
        outCreatedModified[1] = obj.getModifiedTime();
        return true;
    }

    @VisibleForNative
    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
        }

        String path = obj.getPath().toString();
        int pathLen = Integer.min(path.length(), 4096);
        path.getChars(0, pathLen, outFilePath, 0);
        outFilePath[pathLen] = 0;

        outFileLengthFormat[0] = obj.getSize();
        outFileLengthFormat[1] = obj.getFormat();
        return MtpConstants.RESPONSE_OK;
    }

    private int getObjectFormat(int handle) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return -1;
        }
        return obj.getFormat();
    }

    private byte[] getThumbnailProcess(String path, Bitmap bitmap) {
        try {
            if (bitmap == null) {
                Log.d(TAG, "getThumbnailProcess: Fail to generate thumbnail. Probably unsupported or corrupted image");
                return null;
            }

            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteStream);

            if (byteStream.size() > MAX_THUMB_SIZE)
                return null;

            byte[] byteArray = byteStream.toByteArray();

            return byteArray;
        } catch (OutOfMemoryError oomEx) {
            Log.w(TAG, "OutOfMemoryError:" + oomEx);
        }
        return null;
    }

    @VisibleForNative
    @VisibleForTesting
    public boolean getThumbnailInfo(int handle, long[] outLongs) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return false;
        }

        String path = obj.getPath().toString();
        switch (obj.getFormat()) {
            case MtpConstants.FORMAT_HEIF:
            case MtpConstants.FORMAT_EXIF_JPEG:
            case MtpConstants.FORMAT_JFIF:
                try {
                    ExifInterface exif = new ExifInterface(path);
                    long[] thumbOffsetAndSize = exif.getThumbnailRange();
                    outLongs[0] = thumbOffsetAndSize != null ? thumbOffsetAndSize[1] : 0;
                    outLongs[1] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_X_DIMENSION, 0);
                    outLongs[2] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_Y_DIMENSION, 0);
                    return true;
                } catch (IOException e) {
                    // ignore and fall through
                }

// Note: above formats will fall through and go on below thumbnail generation if Exif processing fails
            case MtpConstants.FORMAT_PNG:
            case MtpConstants.FORMAT_GIF:
            case MtpConstants.FORMAT_BMP:
                outLongs[0] = MAX_THUMB_SIZE;
            // only non-zero Width & Height needed. Actual size will be retrieved upon getThumbnailData by Host
                outLongs[1] = 320;
                outLongs[2] = 240;
                return true;
        }
        return false;
    }

    @VisibleForNative
    @VisibleForTesting
    public byte[] getThumbnailData(int handle) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return null;
        }

        String path = obj.getPath().toString();
        switch (obj.getFormat()) {
            case MtpConstants.FORMAT_HEIF:
            case MtpConstants.FORMAT_EXIF_JPEG:
            case MtpConstants.FORMAT_JFIF:
                try {
                    ExifInterface exif = new ExifInterface(path);
                    return exif.getThumbnail();
                } catch (IOException e) {
                    // ignore and fall through
                }

// Note: above formats will fall through and go on below thumbnail generation if Exif processing fails
            case MtpConstants.FORMAT_PNG:
            case MtpConstants.FORMAT_GIF:
            case MtpConstants.FORMAT_BMP:
                {
                    Bitmap bitmap = ThumbnailUtils.createImageThumbnail(path, MediaStore.Images.Thumbnails.MINI_KIND);
                    byte[] byteArray = getThumbnailProcess(path, bitmap);

                    return byteArray;
                }
        }
        return null;
    }

    @VisibleForNative
    private int beginDeleteObject(int handle) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
        }
        if (!mManager.beginRemoveObject(obj)) {
            return MtpConstants.RESPONSE_GENERAL_ERROR;
        }
        return MtpConstants.RESPONSE_OK;
    }

    @VisibleForNative
    private void endDeleteObject(int handle, boolean success) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
            return;
        }
        if (!mManager.endRemoveObject(obj, success))
            Log.e(TAG, "Failed to end remove object");
        if (success)
            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 {
            // Delete the object(s) from MediaProvider, but ignore errors.
            if (isDir) {
                // recursive case - delete all children first
                mMediaProvider.delete(objectsUri,
                        // the 'like' makes it use the index, the 'lower()' makes it correct
                        // when the path contains sqlite wildcard characters
                        "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
                        new String[]{path + "/%", Integer.toString(path.toString().length() + 1),
                                path.toString() + "/"});
            }

            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);
            }
        } catch (Exception e) {
            Log.d(TAG, "Failed to delete " + path + " from MediaProvider");
        }
    }

    @VisibleForNative
    private int[] getObjectReferences(int handle) {
        return null;
    }

    @VisibleForNative
    private int setObjectReferences(int handle, int[] references) {
        return MtpConstants.RESPONSE_OPERATION_NOT_SUPPORTED;
    }

    @VisibleForNative
    private long mNativeContext;

    private native final void native_setup();
    private native final void native_finalize();
}
