/*
 * 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.database.Cursor;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.system.Os;
import android.system.OsConstants;
import android.provider.DocumentsContract;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeoutException;

import static com.android.mtp.MtpDatabase.strings;
import static com.android.mtp.TestUtil.OPERATIONS_SUPPORTED;

@MediumTest
public class MtpDocumentsProviderTest extends AndroidTestCase {
    private final static Uri ROOTS_URI =
            DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY);
    private TestContentResolver mResolver;
    private MtpDocumentsProvider mProvider;
    private TestMtpManager mMtpManager;
    private final TestResources mResources = new TestResources();
    private MtpDatabase mDatabase;

    @Override
    public void setUp() throws IOException {
        mResolver = new TestContentResolver();
        mMtpManager = new TestMtpManager(getContext());
    }

    @Override
    public void tearDown() {
        mProvider.shutdown();
        MtpDatabase.deleteDatabase(getContext());
    }

    public void testOpenAndCloseDevice() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0,
                "Device A",
                null /* deviceKey */,
                false /* unopened */,
                new MtpRoot[] {
                    new MtpRoot(
                            0 /* deviceId */,
                            1 /* storageId */,
                            "Storage A" /* volume description */,
                            1024 /* free space */,
                            2048 /* total space */,
                            "" /* no volume identifier */)
                },
                OPERATIONS_SUPPORTED,
                null));

        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);

        mProvider.openDevice(0);
        mResolver.waitForNotification(ROOTS_URI, 2);

        mProvider.closeDevice(0);
        mResolver.waitForNotification(ROOTS_URI, 3);
    }

    public void testOpenAndCloseErrorDevice() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        try {
            mProvider.openDevice(1);
            fail();
        } catch (Throwable error) {
            assertTrue(error instanceof IOException);
        }
        assertEquals(0, mProvider.getOpenedDeviceRecordsCache().length);

        // Check if the following notification is the first one or not.
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0,
                "Device A",
                null /* deviceKey */,
                false /* unopened */,
                new MtpRoot[] {
                    new MtpRoot(
                            0 /* deviceId */,
                            1 /* storageId */,
                            "Storage A" /* volume description */,
                            1024 /* free space */,
                            2048 /* total space */,
                            "" /* no volume identifier */)
                },
                OPERATIONS_SUPPORTED,
                null));
        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);
        mProvider.openDevice(0);
        mResolver.waitForNotification(ROOTS_URI, 2);
    }

    public void testOpenDeviceOnDemand() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0,
                "Device A",
                null /* deviceKey */,
                false /* unopened */,
                new MtpRoot[] {
                    new MtpRoot(
                            0 /* deviceId */,
                            1 /* storageId */,
                            "Storage A" /* volume description */,
                            1024 /* free space */,
                            2048 /* total space */,
                            "" /* no volume identifier */)
                },
                OPERATIONS_SUPPORTED,
                null));
        mMtpManager.setObjectHandles(0, 1, -1, new int[0]);
        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);
        final String[] columns = new String[] {
                DocumentsContract.Root.COLUMN_TITLE,
                DocumentsContract.Root.COLUMN_DOCUMENT_ID
        };
        try (final Cursor cursor = mProvider.queryRoots(columns)) {
            assertEquals(1, cursor.getCount());
            assertTrue(cursor.moveToNext());
            assertEquals("Device A", cursor.getString(0));
            assertEquals(1, cursor.getLong(1));
        }
        {
            final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
            assertEquals(0, openedDevice.length);
        }
        // Device is opened automatically when querying its children.
        try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {}

        {
            final MtpDeviceRecord[] openedDevice = mProvider.getOpenedDeviceRecordsCache();
            assertEquals(1, openedDevice.length);
            assertEquals(0, openedDevice[0].deviceId);
        }
    }

    public void testQueryRoots() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0,
                "Device A",
                "Device key A",
                false /* unopened */,
                new MtpRoot[] {
                        new MtpRoot(
                                0 /* deviceId */,
                                1 /* storageId */,
                                "Storage A" /* volume description */,
                                1024 /* free space */,
                                2048 /* total space */,
                                "" /* no volume identifier */)
                },
                OPERATIONS_SUPPORTED,
                null));
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                1,
                "Device B",
                "Device key B",
                false /* unopened */,
                new MtpRoot[] {
                    new MtpRoot(
                            1 /* deviceId */,
                            1 /* storageId */,
                            "Storage B" /* volume description */,
                            2048 /* free space */,
                            4096 /* total space */,
                            "Identifier B" /* no volume identifier */)
                },
                new int[0] /* No operations supported */,
                null));

        {
            mProvider.openDevice(0);
            mResolver.waitForNotification(ROOTS_URI, 1);
            final Cursor cursor = mProvider.queryRoots(null);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            assertEquals("1", cursor.getString(0));
            assertEquals(
                    Root.FLAG_SUPPORTS_IS_CHILD |
                    Root.FLAG_SUPPORTS_CREATE |
                    Root.FLAG_LOCAL_ONLY,
                    cursor.getInt(1));
            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
            assertEquals("Device A Storage A", cursor.getString(3));
            assertEquals("1", cursor.getString(4));
            assertEquals(1024, cursor.getInt(5));
        }

        {
            mProvider.openDevice(1);
            mResolver.waitForNotification(ROOTS_URI, 2);
            final Cursor cursor = mProvider.queryRoots(null);
            assertEquals(2, cursor.getCount());
            cursor.moveToNext();
            cursor.moveToNext();
            assertEquals("2", cursor.getString(0));
            assertEquals(
                    Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_LOCAL_ONLY, cursor.getInt(1));
            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
            assertEquals("Device B Storage B", cursor.getString(3));
            assertEquals("2", cursor.getString(4));
            assertEquals(2048, cursor.getInt(5));
        }
    }

    public void testQueryRoots_error() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0,
                "Device A",
                "Device key A",
                false /* unopened */,
                new MtpRoot[0],
                OPERATIONS_SUPPORTED,
                null));
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                1,
                "Device B",
                "Device key B",
                false /* unopened */,
                new MtpRoot[] {
                    new MtpRoot(
                            1 /* deviceId */,
                            1 /* storageId */,
                            "Storage B" /* volume description */,
                            2048 /* free space */,
                            4096 /* total space */,
                            "Identifier B" /* no volume identifier */)
                },
                OPERATIONS_SUPPORTED,
                null));
        {
            mProvider.openDevice(0);
            mResolver.waitForNotification(ROOTS_URI, 1);

            mProvider.openDevice(1);
            mResolver.waitForNotification(ROOTS_URI, 2);

            final Cursor cursor = mProvider.queryRoots(null);
            assertEquals(2, cursor.getCount());

            cursor.moveToNext();
            assertEquals("1", cursor.getString(0));
            assertEquals(
                    Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
                    cursor.getInt(1));
            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
            assertEquals("Device A", cursor.getString(3));
            assertEquals("1", cursor.getString(4));
            assertEquals(0, cursor.getInt(5));

            cursor.moveToNext();
            assertEquals("2", cursor.getString(0));
            assertEquals(
                    Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY,
                    cursor.getInt(1));
            assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
            assertEquals("Device B Storage B", cursor.getString(3));
            assertEquals("2", cursor.getString(4));
            assertEquals(2048, cursor.getInt(5));
        }
    }

    public void testQueryDocument() throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        setupDocuments(
                0,
                0,
                MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
                "1",
                new MtpObjectInfo[] {
                        new MtpObjectInfo.Builder()
                                .setObjectHandle(100)
                                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
                                .setName("image.jpg")
                                .setDateModified(1422716400000L)
                                .setCompressedSize(1024 * 1024 * 5)
                                .setThumbCompressedSize(50 * 1024)
                                .build()
                });

        final Cursor cursor = mProvider.queryDocument("3", null);
        assertEquals(1, cursor.getCount());

        cursor.moveToNext();

        assertEquals("3", cursor.getString(0));
        assertEquals("image/jpeg", cursor.getString(1));
        assertEquals("image.jpg", cursor.getString(2));
        assertEquals(1422716400000L, cursor.getLong(3));
        assertEquals(
                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
                DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL |
                DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
                cursor.getInt(4));
        assertEquals(1024 * 1024 * 5, cursor.getInt(5));
    }

    public void testQueryDocument_directory()
            throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        setupDocuments(
                0,
                0,
                MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
                "1",
                new MtpObjectInfo[] {
                        new MtpObjectInfo.Builder()
                                .setObjectHandle(2)
                                .setStorageId(1)
                                .setFormat(MtpConstants.FORMAT_ASSOCIATION)
                                .setName("directory")
                                .setDateModified(1422716400000L)
                                .build()
                });

        final Cursor cursor = mProvider.queryDocument("3", null);
        assertEquals(1, cursor.getCount());

        cursor.moveToNext();
        assertEquals("3", cursor.getString(0));
        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
        assertEquals("directory", cursor.getString(2));
        assertEquals(1422716400000L, cursor.getLong(3));
        assertEquals(
                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE,
                cursor.getInt(4));
        assertEquals(0, cursor.getInt(5));
    }

    public void testQueryDocument_forStorage()
            throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(
                        0 /* deviceId */,
                        1 /* storageId */,
                        "Storage A" /* volume description */,
                        1024 /* free space */,
                        4096 /* total space */,
                        "" /* no volume identifier */)
        });
        final Cursor cursor = mProvider.queryDocument("2", null);
        assertEquals(1, cursor.getCount());

        cursor.moveToNext();
        assertEquals("2", cursor.getString(0));
        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
        assertEquals("Storage A", cursor.getString(2));
        assertTrue(cursor.isNull(3));
        assertEquals(DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE, cursor.getInt(4));
        assertEquals(3072, cursor.getInt(5));
    }

    public void testQueryDocument_forDeviceWithSingleStorage()
            throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(
                        0 /* deviceId */,
                        1 /* storageId */,
                        "Storage A" /* volume description */,
                        1024 /* free space */,
                        4096 /* total space */,
                        "" /* no volume identifier */)
        });
        final Cursor cursor = mProvider.queryDocument("1", null);
        assertEquals(1, cursor.getCount());

        cursor.moveToNext();
        assertEquals("1", cursor.getString(0));
        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
        assertEquals("Device Storage A", cursor.getString(2));
        assertTrue(cursor.isNull(3));
        assertEquals(DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE, cursor.getInt(4));
        assertTrue(cursor.isNull(5));
    }

    public void testQueryDocument_forDeviceWithTwoStorages()
            throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(
                        0 /* deviceId */,
                        1 /* storageId */,
                        "Storage A" /* volume description */,
                        1024 /* free space */,
                        4096 /* total space */,
                        "" /* no volume identifier */),
                new MtpRoot(
                        0 /* deviceId */,
                        2 /* storageId */,
                        "Storage B" /* volume description */,
                        1024 /* free space */,
                        4096 /* total space */,
                        "" /* no volume identifier */)
        });
        final Cursor cursor = mProvider.queryDocument("1", null);
        assertEquals(1, cursor.getCount());

        cursor.moveToNext();
        assertEquals("1", cursor.getString(0));
        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
        assertEquals("Device", cursor.getString(2));
        assertTrue(cursor.isNull(3));
        assertEquals(0, cursor.getInt(4));
        assertTrue(cursor.isNull(5));
    }

    public void testQueryChildDocuments() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        setupDocuments(
                0,
                0,
                MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
                "1",
                new MtpObjectInfo[] {
                        new MtpObjectInfo.Builder()
                                .setObjectHandle(100)
                                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
                                .setName("image.jpg")
                                .setCompressedSize(1024 * 1024 * 5)
                                .setThumbCompressedSize(5 * 1024)
                                .setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY)
                                .build()
                });

        final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null);
        assertEquals(1, cursor.getCount());

        assertTrue(cursor.moveToNext());
        assertEquals("3", cursor.getString(0));
        assertEquals("image/jpeg", cursor.getString(1));
        assertEquals("image.jpg", cursor.getString(2));
        assertEquals(0, cursor.getLong(3));
        assertEquals(Document.FLAG_SUPPORTS_THUMBNAIL
                | Document.FLAG_SUPPORTS_METADATA, cursor.getInt(4));
        assertEquals(1024 * 1024 * 5, cursor.getInt(5));

        cursor.close();
    }

    public void testQueryChildDocuments_cursorError() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        try {
            mProvider.queryChildDocuments("1", null, (String) null);
            fail();
        } catch (FileNotFoundException error) {}
    }

    public void testQueryChildDocuments_documentError() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
        try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {
            assertEquals(0, cursor.getCount());
            assertFalse(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
        }
    }

    public void testDeleteDocument() throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 0, "Storage", 0, 0, "")
        });
        setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
                new MtpObjectInfo.Builder()
                    .setName("test.txt")
                    .setObjectHandle(1)
                    .setParent(-1)
                    .build()
        });

        mProvider.deleteDocument("3");
        assertEquals(1, mResolver.getChangeCount(
                DocumentsContract.buildChildDocumentsUri(
                        MtpDocumentsProvider.AUTHORITY, "1")));
    }

    public void testDeleteDocument_error()
            throws IOException, InterruptedException, TimeoutException {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 0, "Storage", 0, 0, "")
        });
        setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
                new MtpObjectInfo.Builder()
                    .setName("test.txt")
                    .setObjectHandle(1)
                    .setParent(-1)
                    .build()
        });
        try {
            mProvider.deleteDocument("4");
            fail();
        } catch (Throwable e) {
            assertTrue(e instanceof IOException);
        }
        assertEquals(0, mResolver.getChangeCount(
                DocumentsContract.buildChildDocumentsUri(
                        MtpDocumentsProvider.AUTHORITY, "1")));
    }

    public void testOpenDocument() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 0, "Storage", 0, 0, "")
        });
        final byte[] bytes = "Hello world".getBytes();
        setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
                new MtpObjectInfo.Builder()
                        .setName("test.txt")
                        .setObjectHandle(1)
                        .setCompressedSize(bytes.length)
                        .setParent(-1)
                        .build()
        });
        mMtpManager.setImportFileBytes(0, 1, bytes);
        try (final ParcelFileDescriptor fd = mProvider.openDocument("3", "r", null)) {
            final byte[] readBytes = new byte[5];
            assertEquals(6, Os.lseek(fd.getFileDescriptor(), 6, OsConstants.SEEK_SET));
            assertEquals(5, Os.read(fd.getFileDescriptor(), readBytes, 0, 5));
            assertTrue(Arrays.equals("world".getBytes(), readBytes));

            assertEquals(0, Os.lseek(fd.getFileDescriptor(), 0, OsConstants.SEEK_SET));
            assertEquals(5, Os.read(fd.getFileDescriptor(), readBytes, 0, 5));
            assertTrue(Arrays.equals("Hello".getBytes(), readBytes));
        }
    }

    public void testOpenDocument_shortBytes() throws Exception {
        mMtpManager = new TestMtpManager(getContext()) {
            @Override
            MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
                if (objectHandle == 1) {
                    return new MtpObjectInfo.Builder(super.getObjectInfo(deviceId, objectHandle))
                            .setObjectHandle(1).setCompressedSize(1024 * 1024).build();
                }

                return super.getObjectInfo(deviceId, objectHandle);
            }
        };
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 0, "Storage", 0, 0, "")
        });
        final byte[] bytes = "Hello world".getBytes();
        setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
                new MtpObjectInfo.Builder()
                        .setName("test.txt")
                        .setObjectHandle(1)
                        .setCompressedSize(bytes.length)
                        .setParent(-1)
                        .build()
        });
        mMtpManager.setImportFileBytes(0, 1, bytes);
        try (final ParcelFileDescriptor fd = mProvider.openDocument("3", "r", null)) {
            final byte[] readBytes = new byte[1024 * 1024];
            assertEquals(11, Os.read(fd.getFileDescriptor(), readBytes, 0, readBytes.length));
        }
    }

    public void testOpenDocument_writing() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage", 0, 0, "")
        });
        final String documentId = mProvider.createDocument("2", "text/plain", "test.txt");
        {
            final ParcelFileDescriptor fd = mProvider.openDocument(documentId, "w", null);
            try (ParcelFileDescriptor.AutoCloseOutputStream stream =
                    new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
                stream.write("Hello".getBytes());
                fd.getFileDescriptor().sync();
            }
        }
        {
            final ParcelFileDescriptor fd = mProvider.openDocument(documentId, "r", null);
            try (ParcelFileDescriptor.AutoCloseInputStream stream =
                    new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
                final byte[] bytes = new byte[5];
                stream.read(bytes);
                assertTrue(Arrays.equals("Hello".getBytes(), bytes));
            }
        }
    }

    public void testBusyDevice() throws Exception {
        mMtpManager = new TestMtpManager(getContext()) {
            @Override
            synchronized MtpDeviceRecord openDevice(int deviceId)
                    throws IOException {
                throw new BusyDeviceException();
            }
        };
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0, "Device A", null /* deviceKey */, false /* unopened */, new MtpRoot[0],
                OPERATIONS_SUPPORTED, null));

        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);

        try (final Cursor cursor = mProvider.queryRoots(null)) {
            assertEquals(1, cursor.getCount());
        }

        try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {
            assertEquals(0, cursor.getCount());
            assertEquals(
                    "error_busy_device",
                    cursor.getExtras().getString(DocumentsContract.EXTRA_ERROR));
        }
    }

    public void testLockedDevice() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0, "Device A", null, false /* unopened */, new MtpRoot[0], OPERATIONS_SUPPORTED,
                null));

        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);

        try (final Cursor cursor = mProvider.queryRoots(null)) {
            assertEquals(1, cursor.getCount());
        }

        try (final Cursor cursor = mProvider.queryChildDocuments("1", null, (String) null)) {
            assertEquals(0, cursor.getCount());
            assertEquals(
                    "error_locked_device",
                    cursor.getExtras().getString(DocumentsContract.EXTRA_ERROR));
        }
    }

    public void testMappingDisconnectedDocuments() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0,
                "Device A",
                "device key",
                true /* opened */,
                new MtpRoot[] {
                    new MtpRoot(
                            0 /* deviceId */,
                            1 /* storageId */,
                            "Storage A" /* volume description */,
                            1024 /* free space */,
                            2048 /* total space */,
                            "" /* no volume identifier */)
                },
                OPERATIONS_SUPPORTED,
                null));

        final String[] names = strings("Directory A", "Directory B", "Directory C");
        final int objectHandleOffset = 100;
        for (int i = 0; i < names.length; i++) {
            final int parentHandle = i == 0 ?
                    MtpManager.OBJECT_HANDLE_ROOT_CHILDREN : objectHandleOffset + i - 1;
            final int objectHandle = i + objectHandleOffset;
            mMtpManager.setObjectHandles(0, 1, parentHandle, new int[] { objectHandle });
            mMtpManager.setObjectInfo(
                    0,
                    new MtpObjectInfo.Builder()
                            .setName(names[i])
                            .setObjectHandle(objectHandle)
                            .setFormat(MtpConstants.FORMAT_ASSOCIATION)
                            .setStorageId(1)
                            .build());
        }

        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);

        final int documentIdOffset = 2;
        for (int i = 0; i < names.length; i++) {
            try (final Cursor cursor = mProvider.queryChildDocuments(
                    String.valueOf(documentIdOffset + i),
                    strings(Document.COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME),
                    (String) null)) {
                assertEquals(1, cursor.getCount());
                cursor.moveToNext();
                assertEquals(String.valueOf(documentIdOffset + i + 1), cursor.getString(0));
                assertEquals(names[i], cursor.getString(1));
            }
        }

        mProvider.closeDevice(0);
        mResolver.waitForNotification(ROOTS_URI, 2);

        mProvider.openDevice(0);
        mResolver.waitForNotification(ROOTS_URI, 3);

        for (int i = 0; i < names.length; i++) {
            mResolver.waitForNotification(DocumentsContract.buildChildDocumentsUri(
                    MtpDocumentsProvider.AUTHORITY,
                    String.valueOf(documentIdOffset + i)), 1);
            try (final Cursor cursor = mProvider.queryChildDocuments(
                    String.valueOf(documentIdOffset + i),
                    strings(Document.COLUMN_DOCUMENT_ID),
                    (String) null)) {
                assertEquals(1, cursor.getCount());
                cursor.moveToNext();
                assertEquals(String.valueOf(documentIdOffset + i + 1), cursor.getString(0));
            }
        }
    }

    public void testCreateDocument() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 100, "Storage A", 100, 100, null)
        });
        final String documentId = mProvider.createDocument("1", "text/plain", "note.txt");
        final Uri deviceUri = DocumentsContract.buildChildDocumentsUri(
                MtpDocumentsProvider.AUTHORITY, "1");
        final Uri storageUri = DocumentsContract.buildChildDocumentsUri(
                MtpDocumentsProvider.AUTHORITY, "2");
        mResolver.waitForNotification(storageUri, 1);
        mResolver.waitForNotification(deviceUri, 1);
        try (final Cursor cursor = mProvider.queryDocument(documentId, null)) {
            assertTrue(cursor.moveToNext());
            assertEquals(
                    "note.txt",
                    cursor.getString(cursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME)));
            assertEquals(
                    "text/plain",
                    cursor.getString(cursor.getColumnIndex(Document.COLUMN_MIME_TYPE)));
        }
    }

    public void testCreateDocument_noWritingSupport() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0, "Device A", null /* deviceKey */, false /* unopened */,
                new MtpRoot[] {
                        new MtpRoot(
                                0 /* deviceId */,
                                1 /* storageId */,
                                "Storage A" /* volume description */,
                                1024 /* free space */,
                                2048 /* total space */,
                                "" /* no volume identifier */)
                },
                new int[0] /* no operations supported */, null));
        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);
        try {
            mProvider.createDocument("1", "text/palin", "note.txt");
            fail();
        } catch (UnsupportedOperationException exception) {}
    }

    public void testOpenDocument_noWritingSupport() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0, "Device A", null /* deviceKey */, false /* unopened */,
                new MtpRoot[] {
                        new MtpRoot(
                                0 /* deviceId */,
                                1 /* storageId */,
                                "Storage A" /* volume description */,
                                1024 /* free space */,
                                2048 /* total space */,
                                "" /* no volume identifier */)
                },
                new int[0] /* no operations supported */, null));
        mMtpManager.setObjectHandles(
                0, 1, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, new int[] { 100 });
        mMtpManager.setObjectInfo(
                0, new MtpObjectInfo.Builder().setObjectHandle(100).setName("note.txt").build());
        mProvider.resumeRootScanner();
        mResolver.waitForNotification(ROOTS_URI, 1);
        try (final Cursor cursor = mProvider.queryChildDocuments(
                "1", strings(Document.COLUMN_DOCUMENT_ID), (String) null)) {
            assertEquals(1, cursor.getCount());
            cursor.moveToNext();
            assertEquals("3", cursor.getString(0));
        }
        try {
            mProvider.openDocument("3", "w", null);
            fail();
        } catch (UnsupportedOperationException exception) {}
    }

    public void testObjectSizeLong() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        mMtpManager.setObjectSizeLong(0, 100, MtpConstants.FORMAT_EXIF_JPEG, 0x400000000L);
        setupDocuments(
                0,
                0,
                MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
                "1",
                new MtpObjectInfo[] {
                        new MtpObjectInfo.Builder()
                                .setObjectHandle(100)
                                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
                                .setName("image.jpg")
                                .setCompressedSize(0xffffffffl)
                                .build()
                });

        final Cursor cursor = mProvider.queryDocument("3", new String[] {
                DocumentsContract.Document.COLUMN_SIZE
        });
        assertEquals(1, cursor.getCount());

        cursor.moveToNext();
        assertEquals(0x400000000L, cursor.getLong(0));
    }

    public void testFindDocumentPath_singleStorage_toRoot() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        setupHierarchyDocuments("1");

        final Path path = mProvider.findDocumentPath(null, "15");
        assertEquals("1", path.getRootId());
        assertEquals(4, path.getPath().size());
        assertEquals("1", path.getPath().get(0));
        assertEquals("3", path.getPath().get(1));
        assertEquals("6", path.getPath().get(2));
        assertEquals("15", path.getPath().get(3));
    }

    public void testFindDocumentPath_singleStorage_toDoc() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        setupHierarchyDocuments("1");

        final Path path = mProvider.findDocumentPath("3", "18");
        assertNull(path.getRootId());
        assertEquals(3, path.getPath().size());
        assertEquals("3", path.getPath().get(0));
        assertEquals("7", path.getPath().get(1));
        assertEquals("18", path.getPath().get(2));
    }

    public void testFindDocumentPath_multiStorage_toRoot() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 0, "Storage A", 1000, 1000, ""),
                new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
        setupHierarchyDocuments("2");

        final Path path = mProvider.findDocumentPath(null, "16");
        assertEquals("2", path.getRootId());
        assertEquals(4, path.getPath().size());
        assertEquals("2", path.getPath().get(0));
        assertEquals("4", path.getPath().get(1));
        assertEquals("7", path.getPath().get(2));
        assertEquals("16", path.getPath().get(3));
    }

    public void testFindDocumentPath_multiStorage_toDoc() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] {
                new MtpRoot(0, 0, "Storage A", 1000, 1000, ""),
                new MtpRoot(0, 1, "Storage B", 1000, 1000, "") });
        setupHierarchyDocuments("2");

        final Path path = mProvider.findDocumentPath("4", "19");
        assertNull(path.getRootId());
        assertEquals(3, path.getPath().size());
        assertEquals("4", path.getPath().get(0));
        assertEquals("8", path.getPath().get(1));
        assertEquals("19", path.getPath().get(2));
    }

    public void testIsChildDocument() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
        setupHierarchyDocuments("1");
        assertTrue(mProvider.isChildDocument("1", "1"));
        assertTrue(mProvider.isChildDocument("1", "14"));
        assertTrue(mProvider.isChildDocument("2", "14"));
        assertTrue(mProvider.isChildDocument("5", "14"));
        assertFalse(mProvider.isChildDocument("3", "14"));
        assertFalse(mProvider.isChildDocument("6", "14"));
    }

    private void setupProvider(int flag) {
        mDatabase = new MtpDatabase(getContext(), flag);
        mProvider = new MtpDocumentsProvider();
        final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
        assertTrue(mProvider.onCreateForTesting(
                getContext(),
                mResources,
                mMtpManager,
                mResolver,
                mDatabase,
                storageManager,
                new TestServiceIntentSender()));
    }

    private String[] getStrings(Cursor cursor) {
        try {
            final String[] results = new String[cursor.getCount()];
            for (int i = 0; cursor.moveToNext(); i++) {
                results[i] = cursor.getString(0);
            }
            return results;
        } finally {
            cursor.close();
        }
    }

    private String[] setupRoots(int deviceId, MtpRoot[] roots)
            throws InterruptedException, TimeoutException, IOException {
        final int changeCount = mResolver.getChangeCount(ROOTS_URI);
        mMtpManager.addValidDevice(
                new MtpDeviceRecord(deviceId, "Device", null /* deviceKey */, false /* unopened */,
                roots, OPERATIONS_SUPPORTED, null));
        mProvider.openDevice(deviceId);
        mResolver.waitForNotification(ROOTS_URI, changeCount + 1);
        return getStrings(mProvider.queryRoots(strings(DocumentsContract.Root.COLUMN_ROOT_ID)));
    }

    private String[] setupDocuments(
            int deviceId,
            int storageId,
            int parentHandle,
            String parentDocumentId,
            MtpObjectInfo[] objects) throws FileNotFoundException {
        final int[] handles = new int[objects.length];
        int i = 0;
        for (final MtpObjectInfo info : objects) {
            handles[i++] = info.getObjectHandle();
            mMtpManager.setObjectInfo(deviceId, info);
        }
        mMtpManager.setObjectHandles(deviceId, storageId, parentHandle, handles);
        return getStrings(mProvider.queryChildDocuments(
                parentDocumentId,
                strings(DocumentsContract.Document.COLUMN_DOCUMENT_ID),
                (String) null));
    }

    static class HierarchyDocument {
        int depth;
        String documentId;
        int objectHandle;
        int parentHandle;

        HierarchyDocument createChildDocument(int newHandle) {
            final HierarchyDocument doc = new HierarchyDocument();
            doc.depth = depth - 1;
            doc.objectHandle = newHandle;
            doc.parentHandle = objectHandle;
            return doc;
        }

        MtpObjectInfo toObjectInfo() {
            return new MtpObjectInfo.Builder()
                    .setName("doc_" + documentId)
                    .setFormat(depth > 0 ?
                            MtpConstants.FORMAT_ASSOCIATION : MtpConstants.FORMAT_TEXT)
                    .setObjectHandle(objectHandle)
                    .setParent(parentHandle)
                    .build();
        }
    }

    private void setupHierarchyDocuments(String documentId) throws Exception {
        final Queue<HierarchyDocument> ids = new LinkedList<>();
        final HierarchyDocument firstDocument = new HierarchyDocument();
        firstDocument.depth = 3;
        firstDocument.documentId = documentId;
        firstDocument.objectHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
        ids.add(firstDocument);

        int objectHandle = 100;
        while (!ids.isEmpty()) {
            final HierarchyDocument document = ids.remove();
            final HierarchyDocument[] children = new HierarchyDocument[] {
                    document.createChildDocument(objectHandle++),
                    document.createChildDocument(objectHandle++),
                    document.createChildDocument(objectHandle++),
            };
            final String[] childDocIds = setupDocuments(
                    0, 0, document.objectHandle, document.documentId, new MtpObjectInfo[] {
                            children[0].toObjectInfo(),
                            children[1].toObjectInfo(),
                            children[2].toObjectInfo(),
                    });
            children[0].documentId = childDocIds[0];
            children[1].documentId = childDocIds[1];
            children[2].documentId = childDocIds[2];

            if (children[0].depth > 0) {
                ids.add(children[0]);
                ids.add(children[1]);
                ids.add(children[2]);
            }
        }
    }
}
