/*
 * Copyright (C) 2015 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 com.android.mtp;

import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriPermission;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDiskIOException;
import android.graphics.Point;
import android.media.MediaFile;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.ProxyFileDescriptorCallback;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import android.provider.MetadataReader;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.util.Log;

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

import libcore.io.IoUtils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * DocumentsProvider for MTP devices.
 */
public class MtpDocumentsProvider extends DocumentsProvider {
    static final String AUTHORITY = "com.android.mtp.documents";
    static final String TAG = "MtpDocumentsProvider";
    static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON,
            Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
            Root.COLUMN_AVAILABLE_BYTES,
    };
    static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE,
            Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED,
            Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
    };

    static final boolean DEBUG = false;

    private final Object mDeviceListLock = new Object();

    private static MtpDocumentsProvider sSingleton;

    private MtpManager mMtpManager;
    private ContentResolver mResolver;
    @GuardedBy("mDeviceListLock")
    private Map<Integer, DeviceToolkit> mDeviceToolkits;
    private RootScanner mRootScanner;
    private Resources mResources;
    private MtpDatabase mDatabase;
    private ServiceIntentSender mIntentSender;
    private Context mContext;
    private StorageManager mStorageManager;

    /**
     * Provides singleton instance to MtpDocumentsService.
     */
    static MtpDocumentsProvider getInstance() {
        return sSingleton;
    }

    @Override
    public boolean onCreate() {
        sSingleton = this;
        mContext = getContext();
        mResources = getContext().getResources();
        mMtpManager = new MtpManager(getContext());
        mResolver = getContext().getContentResolver();
        mDeviceToolkits = new HashMap<>();
        mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
        mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
        mIntentSender = new ServiceIntentSender(getContext());
        mStorageManager = getContext().getSystemService(StorageManager.class);

        // Check boot count and cleans database if it's first time to launch MtpDocumentsProvider
        // after booting.
        try {
            final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1);
            final int lastBootCount = mDatabase.getLastBootCount();
            if (bootCount != -1 && bootCount != lastBootCount) {
                mDatabase.setLastBootCount(bootCount);
                final List<UriPermission> permissions =
                        mResolver.getOutgoingPersistedUriPermissions();
                final Uri[] uris = new Uri[permissions.size()];
                for (int i = 0; i < permissions.size(); i++) {
                    uris[i] = permissions.get(i).getUri();
                }
                mDatabase.cleanDatabase(uris);
            }
        } catch (SQLiteDiskIOException error) {
            // It can happen due to disk shortage.
            Log.e(TAG, "Failed to clean database.", error);
            return false;
        } catch (SecurityException exSec) {
            // For UriPermission.
            Log.w(TAG, "SecurityException:", exSec);
            return false;
        }

        resume();
        return true;
    }

    @VisibleForTesting
    boolean onCreateForTesting(
            Context context,
            Resources resources,
            MtpManager mtpManager,
            ContentResolver resolver,
            MtpDatabase database,
            StorageManager storageManager,
            ServiceIntentSender intentSender) {
        mContext = context;
        mResources = resources;
        mMtpManager = mtpManager;
        mResolver = resolver;
        mDeviceToolkits = new HashMap<>();
        mDatabase = database;
        mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
        mIntentSender = intentSender;
        mStorageManager = storageManager;

        resume();
        return true;
    }

    @Override
    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
        if (projection == null) {
            projection = MtpDocumentsProvider.DEFAULT_ROOT_PROJECTION;
        }
        final Cursor cursor = mDatabase.queryRoots(mResources, projection);
        cursor.setNotificationUri(
                mResolver, DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY));
        return cursor;
    }

    @Override
    public Cursor queryDocument(String documentId, String[] projection)
            throws FileNotFoundException {
        if (projection == null) {
            projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
        }
        final Cursor cursor = mDatabase.queryDocument(documentId, projection);
        final int cursorCount = cursor.getCount();
        if (cursorCount == 0) {
            cursor.close();
            throw new FileNotFoundException();
        } else if (cursorCount != 1) {
            cursor.close();
            Log.wtf(TAG, "Unexpected cursor size: " + cursorCount);
            return null;
        }

        final Identifier identifier = mDatabase.createIdentifier(documentId);
        if (identifier.mDocumentType != MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
            return cursor;
        }
        final String[] storageDocIds = mDatabase.getStorageDocumentIds(documentId);
        if (storageDocIds.length != 1) {
            return mDatabase.queryDocument(documentId, projection);
        }

        // If the documentId specifies a device having exact one storage, we repalce some device
        // attributes with the storage attributes.
        try {
            final String storageName;
            final int storageFlags;
            try (final Cursor storageCursor = mDatabase.queryDocument(
                    storageDocIds[0],
                    MtpDatabase.strings(Document.COLUMN_DISPLAY_NAME, Document.COLUMN_FLAGS))) {
                if (!storageCursor.moveToNext()) {
                    throw new FileNotFoundException();
                }
                storageName = storageCursor.getString(0);
                storageFlags = storageCursor.getInt(1);
            }

            cursor.moveToNext();
            final ContentValues values = new ContentValues();
            DatabaseUtils.cursorRowToContentValues(cursor, values);
            if (values.containsKey(Document.COLUMN_DISPLAY_NAME)) {
                values.put(Document.COLUMN_DISPLAY_NAME, mResources.getString(
                        R.string.root_name,
                        values.getAsString(Document.COLUMN_DISPLAY_NAME),
                        storageName));
            }
            values.put(Document.COLUMN_FLAGS, storageFlags);
            final MatrixCursor output = new MatrixCursor(projection, 1);
            MtpDatabase.putValuesToCursor(values, output);
            return output;
        } finally {
            cursor.close();
        }
    }

    @Override
    public Cursor queryChildDocuments(String parentDocumentId,
            String[] projection, String sortOrder) throws FileNotFoundException {
        if (DEBUG) {
            Log.d(TAG, "queryChildDocuments: " + parentDocumentId);
        }
        if (projection == null) {
            projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
        }
        Identifier parentIdentifier = mDatabase.createIdentifier(parentDocumentId);
        try {
            openDevice(parentIdentifier.mDeviceId);
            if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
                final String[] storageDocIds = mDatabase.getStorageDocumentIds(parentDocumentId);
                if (storageDocIds.length == 0) {
                    // Remote device does not provide storages. Maybe it is locked.
                    return createErrorCursor(projection, R.string.error_locked_device);
                } else if (storageDocIds.length > 1) {
                    // Returns storage list from database.
                    return mDatabase.queryChildDocuments(projection, parentDocumentId);
                }

                // Exact one storage is found. Skip storage and returns object in the single
                // storage.
                parentIdentifier = mDatabase.createIdentifier(storageDocIds[0]);
            }

            // Returns object list from document loader.
            return getDocumentLoader(parentIdentifier).queryChildDocuments(
                    projection, parentIdentifier);
        } catch (BusyDeviceException exception) {
            return createErrorCursor(projection, R.string.error_busy_device);
        } catch (IOException exception) {
            Log.e(MtpDocumentsProvider.TAG, "queryChildDocuments", exception);
            throw new FileNotFoundException(exception.getMessage());
        }
    }

    @Override
    public ParcelFileDescriptor openDocument(
            String documentId, String mode, CancellationSignal signal)
                    throws FileNotFoundException {
        if (DEBUG) {
            Log.d(TAG, "openDocument: " + documentId);
        }
        final Identifier identifier = mDatabase.createIdentifier(documentId);
        try {
            openDevice(identifier.mDeviceId);
            final MtpDeviceRecord device = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
            // Turn off MODE_CREATE because openDocument does not allow to create new files.
            final int modeFlag =
                    ParcelFileDescriptor.parseMode(mode) & ~ParcelFileDescriptor.MODE_CREATE;
            if ((modeFlag & ParcelFileDescriptor.MODE_READ_ONLY) != 0) {
                long fileSize;
                try {
                    fileSize = getFileSize(documentId);
                } catch (UnsupportedOperationException exception) {
                    fileSize = -1;
                }
                if (MtpDeviceRecord.isPartialReadSupported(
                        device.operationsSupported, fileSize)) {

                    return mStorageManager.openProxyFileDescriptor(
                            modeFlag,
                            new MtpProxyFileDescriptorCallback(Integer.parseInt(documentId)));
                } else {
                    // If getPartialObject{|64} are not supported for the device, returns
                    // non-seekable pipe FD instead.
                    return getPipeManager(identifier).readDocument(mMtpManager, identifier);
                }
            } else if ((modeFlag & ParcelFileDescriptor.MODE_WRITE_ONLY) != 0) {
                // TODO: Clear the parent document loader task (if exists) and call notify
                // when writing is completed.
                if (MtpDeviceRecord.isWritingSupported(device.operationsSupported)) {
                    return mStorageManager.openProxyFileDescriptor(
                            modeFlag,
                            new MtpProxyFileDescriptorCallback(Integer.parseInt(documentId)));
                } else {
                    throw new UnsupportedOperationException(
                            "The device does not support writing operation.");
                }
            } else {
                // TODO: Add support for "rw" mode.
                throw new UnsupportedOperationException("The provider does not support 'rw' mode.");
            }
        } catch (FileNotFoundException | RuntimeException error) {
            Log.e(MtpDocumentsProvider.TAG, "openDocument", error);
            throw error;
        } catch (IOException error) {
            Log.e(MtpDocumentsProvider.TAG, "openDocument", error);
            throw new IllegalStateException(error);
        }
    }

    @Override
    public AssetFileDescriptor openDocumentThumbnail(
            String documentId,
            Point sizeHint,
            CancellationSignal signal) throws FileNotFoundException {
        final Identifier identifier = mDatabase.createIdentifier(documentId);
        try {
            openDevice(identifier.mDeviceId);
            return new AssetFileDescriptor(
                    getPipeManager(identifier).readThumbnail(mMtpManager, identifier),
                    0,  // Start offset.
                    AssetFileDescriptor.UNKNOWN_LENGTH);
        } catch (IOException error) {
            Log.e(MtpDocumentsProvider.TAG, "openDocumentThumbnail", error);
            throw new FileNotFoundException(error.getMessage());
        }
    }

    @Override
    public void deleteDocument(String documentId) throws FileNotFoundException {
        try {
            final Identifier identifier = mDatabase.createIdentifier(documentId);
            openDevice(identifier.mDeviceId);
            final Identifier parentIdentifier = mDatabase.getParentIdentifier(documentId);
            mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
            mDatabase.deleteDocument(documentId);
            getDocumentLoader(parentIdentifier).cancelTask(parentIdentifier);
            notifyChildDocumentsChange(parentIdentifier.mDocumentId);
            if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
                // If the parent is storage, the object might be appeared as child of device because
                // we skip storage when the device has only one storage.
                final Identifier deviceIdentifier = mDatabase.getParentIdentifier(
                        parentIdentifier.mDocumentId);
                notifyChildDocumentsChange(deviceIdentifier.mDocumentId);
            }
        } catch (IOException error) {
            Log.e(MtpDocumentsProvider.TAG, "deleteDocument", error);
            throw new FileNotFoundException(error.getMessage());
        }
    }

    @Override
    public void onTrimMemory(int level) {
        synchronized (mDeviceListLock) {
            for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
                toolkit.mDocumentLoader.clearCompletedTasks();
            }
        }
    }

    @Override
    public String createDocument(String parentDocumentId, String mimeType, String displayName)
            throws FileNotFoundException {
        if (DEBUG) {
            Log.d(TAG, "createDocument: " + displayName);
        }
        final Identifier parentId;
        final MtpDeviceRecord record;
        final ParcelFileDescriptor[] pipe;
        try {
            parentId = mDatabase.createIdentifier(parentDocumentId);
            openDevice(parentId.mDeviceId);
            record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
            if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
                throw new UnsupportedOperationException(
                        "Writing operation is not supported by the device.");
            }

            final int parentObjectHandle;
            final int storageId;
            switch (parentId.mDocumentType) {
                case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE:
                    final String[] storageDocumentIds =
                            mDatabase.getStorageDocumentIds(parentId.mDocumentId);
                    if (storageDocumentIds.length == 1) {
                        final String newDocumentId =
                                createDocument(storageDocumentIds[0], mimeType, displayName);
                        notifyChildDocumentsChange(parentDocumentId);
                        return newDocumentId;
                    } else {
                        throw new UnsupportedOperationException(
                                "Cannot create a file under the device.");
                    }
                case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE:
                    storageId = parentId.mStorageId;
                    parentObjectHandle = -1;
                    break;
                case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT:
                    storageId = parentId.mStorageId;
                    parentObjectHandle = parentId.mObjectHandle;
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected document type.");
            }

            pipe = ParcelFileDescriptor.createReliablePipe();
            int objectHandle = -1;
            MtpObjectInfo info = null;
            try {
                pipe[0].close();  // 0 bytes for a new document.

                final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
                        MtpConstants.FORMAT_ASSOCIATION :
                        MediaFile.getFormatCode(displayName, mimeType);
                info = new MtpObjectInfo.Builder()
                        .setStorageId(storageId)
                        .setParent(parentObjectHandle)
                        .setFormat(formatCode)
                        .setName(displayName)
                        .build();

                final String[] parts = FileUtils.splitFileName(mimeType, displayName);
                final String baseName = parts[0];
                final String extension = parts[1];
                for (int i = 0; i <= 32; i++) {
                    final MtpObjectInfo infoUniqueName;
                    if (i == 0) {
                        infoUniqueName = info;
                    } else {
                        String suffixedName = baseName + " (" + i + " )";
                        if (!extension.isEmpty()) {
                            suffixedName += "." + extension;
                        }
                        infoUniqueName =
                                new MtpObjectInfo.Builder(info).setName(suffixedName).build();
                    }
                    try {
                        objectHandle = mMtpManager.createDocument(
                                parentId.mDeviceId, infoUniqueName, pipe[1]);
                        break;
                    } catch (SendObjectInfoFailure exp) {
                        // This can be caused when we have an existing file with the same name.
                        continue;
                    }
                }
            } finally {
                pipe[1].close();
            }
            if (objectHandle == -1) {
                throw new IllegalArgumentException(
                        "The file name \"" + displayName + "\" is conflicted with existing files " +
                        "and the provider failed to find unique name.");
            }
            final MtpObjectInfo infoWithHandle =
                    new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
            final String documentId = mDatabase.putNewDocument(
                    parentId.mDeviceId, parentDocumentId, record.operationsSupported,
                    infoWithHandle, 0l);
            getDocumentLoader(parentId).cancelTask(parentId);
            notifyChildDocumentsChange(parentDocumentId);
            return documentId;
        } catch (FileNotFoundException | RuntimeException error) {
            Log.e(TAG, "createDocument", error);
            throw error;
        } catch (IOException error) {
            Log.e(TAG, "createDocument", error);
            throw new IllegalStateException(error);
        }
    }

    @Override
    public Path findDocumentPath(String parentDocumentId, String childDocumentId)
            throws FileNotFoundException {
        final LinkedList<String> ids = new LinkedList<>();
        final Identifier childIdentifier = mDatabase.createIdentifier(childDocumentId);

        Identifier i = childIdentifier;
        outer: while (true) {
            if (i.mDocumentId.equals(parentDocumentId)) {
                ids.addFirst(i.mDocumentId);
                break;
            }
            switch (i.mDocumentType) {
                case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT:
                    ids.addFirst(i.mDocumentId);
                    i = mDatabase.getParentIdentifier(i.mDocumentId);
                    break;
                case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE: {
                    // Check if there is the multiple storage.
                    final Identifier deviceIdentifier =
                            mDatabase.getParentIdentifier(i.mDocumentId);
                    final String[] storageIds =
                            mDatabase.getStorageDocumentIds(deviceIdentifier.mDocumentId);
                    // Add storage's document ID to the path only when the device has multiple
                    // storages.
                    if (storageIds.length > 1) {
                        ids.addFirst(i.mDocumentId);
                        break outer;
                    }
                    i = deviceIdentifier;
                    break;
                }
                case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE:
                    ids.addFirst(i.mDocumentId);
                    break outer;
            }
        }

        if (parentDocumentId != null) {
            return new Path(null, ids);
        } else {
            return new Path(/* Should be same with root ID */ i.mDocumentId, ids);
        }
    }

    @Override
    public boolean isChildDocument(String parentDocumentId, String documentId) {
        try {
            Identifier identifier = mDatabase.createIdentifier(documentId);
            while (true) {
                if (parentDocumentId.equals(identifier.mDocumentId)) {
                    return true;
                }
                if (identifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
                    return false;
                }
                identifier = mDatabase.getParentIdentifier(identifier.mDocumentId);
            }
        } catch (FileNotFoundException error) {
            return false;
        }
    }

    @Override
    public @Nullable Bundle getDocumentMetadata(String docId) throws FileNotFoundException {
        String mimeType = getDocumentType(docId);

        if (!MetadataReader.isSupportedMimeType(mimeType)) {
            return null;
        }

        InputStream stream = null;
        try {
            stream = new ParcelFileDescriptor.AutoCloseInputStream(
                    openDocument(docId, "r", null));
            Bundle metadata = new Bundle();
            MetadataReader.getMetadata(metadata, stream, mimeType, null);
            return metadata;
        } catch (IOException e) {
            Log.e(TAG, "An error occurred retrieving the metadata", e);
            return null;
        } finally {
            IoUtils.closeQuietly(stream);
        }
    }

    void openDevice(int deviceId) throws IOException {
        synchronized (mDeviceListLock) {
            if (mDeviceToolkits.containsKey(deviceId)) {
                return;
            }
            if (DEBUG) {
                Log.d(TAG, "Open device " + deviceId);
            }
            final MtpDeviceRecord device = mMtpManager.openDevice(deviceId);
            final DeviceToolkit toolkit =
                    new DeviceToolkit(mMtpManager, mResolver, mDatabase, device);
            mDeviceToolkits.put(deviceId, toolkit);
            mIntentSender.sendUpdateNotificationIntent(getOpenedDeviceRecordsCache());
            try {
                mRootScanner.resume().await();
            } catch (InterruptedException error) {
                Log.e(TAG, "openDevice", error);
            }
            // Resume document loader to remap disconnected document ID. Must be invoked after the
            // root scanner resumes.
            toolkit.mDocumentLoader.resume();
        }
    }

    void closeDevice(int deviceId) throws IOException, InterruptedException {
        synchronized (mDeviceListLock) {
            closeDeviceInternal(deviceId);
            mIntentSender.sendUpdateNotificationIntent(getOpenedDeviceRecordsCache());
        }
        mRootScanner.resume();
    }

    MtpDeviceRecord[] getOpenedDeviceRecordsCache() {
        synchronized (mDeviceListLock) {
            final MtpDeviceRecord[] records = new MtpDeviceRecord[mDeviceToolkits.size()];
            int i = 0;
            for (final DeviceToolkit toolkit : mDeviceToolkits.values()) {
                records[i] = toolkit.mDeviceRecord;
                i++;
            }
            return records;
        }
    }

    /**
     * Obtains document ID for the given device ID.
     * @param deviceId
     * @return document ID
     * @throws FileNotFoundException device ID has not been build.
     */
    public String getDeviceDocumentId(int deviceId) throws FileNotFoundException {
        return mDatabase.getDeviceDocumentId(deviceId);
    }

    /**
     * Resumes root scanner to handle the update of device list.
     */
    void resumeRootScanner() {
        if (DEBUG) {
            Log.d(MtpDocumentsProvider.TAG, "resumeRootScanner");
        }
        mRootScanner.resume();
    }

    /**
     * Finalize the content provider for unit tests.
     */
    @Override
    public void shutdown() {
        synchronized (mDeviceListLock) {
            try {
                // Copy the opened key set because it will be modified when closing devices.
                final Integer[] keySet =
                        mDeviceToolkits.keySet().toArray(new Integer[mDeviceToolkits.size()]);
                for (final int id : keySet) {
                    closeDeviceInternal(id);
                }
                mRootScanner.pause();
            } catch (InterruptedException | IOException | TimeoutException e) {
                // It should fail unit tests by throwing runtime exception.
                throw new RuntimeException(e);
            } finally {
                mDatabase.close();
                super.shutdown();
            }
        }
    }

    private void notifyChildDocumentsChange(String parentDocumentId) {
        mResolver.notifyChange(
                DocumentsContract.buildChildDocumentsUri(AUTHORITY, parentDocumentId),
                null,
                false);
    }

    /**
     * Clears MTP identifier in the database.
     */
    private void resume() {
        synchronized (mDeviceListLock) {
            mDatabase.getMapper().clearMapping();
        }
    }

    private void closeDeviceInternal(int deviceId) throws IOException, InterruptedException {
        // TODO: Flush the device before closing (if not closed externally).
        if (!mDeviceToolkits.containsKey(deviceId)) {
            return;
        }
        if (DEBUG) {
            Log.d(TAG, "Close device " + deviceId);
        }
        getDeviceToolkit(deviceId).close();
        mDeviceToolkits.remove(deviceId);
        mMtpManager.closeDevice(deviceId);
    }

    private DeviceToolkit getDeviceToolkit(int deviceId) throws FileNotFoundException {
        synchronized (mDeviceListLock) {
            final DeviceToolkit toolkit = mDeviceToolkits.get(deviceId);
            if (toolkit == null) {
                throw new FileNotFoundException();
            }
            return toolkit;
        }
    }

    private PipeManager getPipeManager(Identifier identifier) throws FileNotFoundException {
        return getDeviceToolkit(identifier.mDeviceId).mPipeManager;
    }

    private DocumentLoader getDocumentLoader(Identifier identifier) throws FileNotFoundException {
        return getDeviceToolkit(identifier.mDeviceId).mDocumentLoader;
    }

    private long getFileSize(String documentId) throws FileNotFoundException {
        final Cursor cursor = mDatabase.queryDocument(
                documentId,
                MtpDatabase.strings(Document.COLUMN_SIZE, Document.COLUMN_DISPLAY_NAME));
        try {
            if (cursor.moveToNext()) {
                if (cursor.isNull(0)) {
                    throw new UnsupportedOperationException();
                }
                return cursor.getLong(0);
            } else {
                throw new FileNotFoundException();
            }
        } finally {
            cursor.close();
        }
    }

    /**
     * Creates empty cursor with specific error message.
     *
     * @param projection Column names.
     * @param stringResId String resource ID of error message.
     * @return Empty cursor with error message.
     */
    private Cursor createErrorCursor(String[] projection, int stringResId) {
        final Bundle bundle = new Bundle();
        bundle.putString(DocumentsContract.EXTRA_ERROR, mResources.getString(stringResId));
        final Cursor cursor = new MatrixCursor(projection);
        cursor.setExtras(bundle);
        return cursor;
    }

    private static class DeviceToolkit implements AutoCloseable {
        public final PipeManager mPipeManager;
        public final DocumentLoader mDocumentLoader;
        public final MtpDeviceRecord mDeviceRecord;

        public DeviceToolkit(MtpManager manager,
                             ContentResolver resolver,
                             MtpDatabase database,
                             MtpDeviceRecord record) {
            mPipeManager = new PipeManager(database);
            mDocumentLoader = new DocumentLoader(record, manager, resolver, database);
            mDeviceRecord = record;
        }

        @Override
        public void close() throws InterruptedException {
            mPipeManager.close();
            mDocumentLoader.close();
        }
    }

    private class MtpProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
        private final int mInode;
        private MtpFileWriter mWriter;

        MtpProxyFileDescriptorCallback(int inode) {
            mInode = inode;
        }

        @Override
        public long onGetSize() throws ErrnoException {
            try {
                return getFileSize(String.valueOf(mInode));
            } catch (FileNotFoundException e) {
                Log.e(TAG, e.getMessage(), e);
                throw new ErrnoException("onGetSize", OsConstants.ENOENT);
            }
        }

        @Override
        public int onRead(long offset, int size, byte[] data) throws ErrnoException {
            try {
                final Identifier identifier = mDatabase.createIdentifier(Integer.toString(mInode));
                final MtpDeviceRecord record = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord;
                if (MtpDeviceRecord.isSupported(
                        record.operationsSupported, MtpConstants.OPERATION_GET_PARTIAL_OBJECT_64)) {

                        return (int) mMtpManager.getPartialObject64(
                                identifier.mDeviceId, identifier.mObjectHandle, offset, size, data);

                }
                if (0 <= offset && offset <= 0xffffffffL && MtpDeviceRecord.isSupported(
                        record.operationsSupported, MtpConstants.OPERATION_GET_PARTIAL_OBJECT)) {
                    return (int) mMtpManager.getPartialObject(
                            identifier.mDeviceId, identifier.mObjectHandle, offset, size, data);
                }
                throw new ErrnoException("onRead", OsConstants.ENOTSUP);
            } catch (IOException e) {
                Log.e(TAG, e.getMessage(), e);
                throw new ErrnoException("onRead", OsConstants.EIO);
            }
        }

        @Override
        public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
            try {
                if (mWriter == null) {
                    mWriter = new MtpFileWriter(mContext, String.valueOf(mInode));
                }
                return mWriter.write(offset, size, data);
            } catch (IOException e) {
                Log.e(TAG, e.getMessage(), e);
                throw new ErrnoException("onWrite", OsConstants.EIO);
            }
        }

        @Override
        public void onFsync() throws ErrnoException {
            tryFsync();
        }

        @Override
        public void onRelease() {
            try {
                tryFsync();
            } catch (ErrnoException error) {
                // Cannot recover from the error at onRelease. Client app should use fsync to
                // ensure the provider writes data correctly.
                Log.e(TAG, "Cannot recover from the error at onRelease.", error);
            } finally {
                if (mWriter != null) {
                    IoUtils.closeQuietly(mWriter);
                }
            }
        }

        private void tryFsync() throws ErrnoException {
            try {
                if (mWriter != null) {
                    final MtpDeviceRecord device =
                            getDeviceToolkit(mDatabase.createIdentifier(
                                    mWriter.getDocumentId()).mDeviceId).mDeviceRecord;
                    mWriter.flush(mMtpManager, mDatabase, device.operationsSupported);
                }
            } catch (IOException e) {
                Log.e(TAG, e.getMessage(), e);
                throw new ErrnoException("onWrite", OsConstants.EIO);
            }
        }
    }
}
