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

Commit 0abde685 authored by Daichi Hirono's avatar Daichi Hirono Committed by Android (Google) Code Review
Browse files

Merge "Add error message for locked device." into nyc-dev

parents 46d53771 2965776b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -27,4 +27,6 @@
    <string name="accessing_notification_description">Don\'t disconnect the device</string>
    <!-- Error message shown in Files app when the connected MTP device is busy. [CHAR LIMIT=150]-->
    <string name="error_busy_device">The other device is busy. You can\'t transfer files until it\'s available.</string>
    <!-- Error message shown in Files app when the connected MTP device may be locked. [CHAR LIMIT=150]-->
    <string name="error_locked_device">No files found. The other device may be locked. If so, unlock it and try again.</string>
</resources>
+11 −10
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import java.io.FileNotFoundException;
import java.util.Objects;
@@ -244,15 +245,16 @@ class MtpDatabase {
    }

    /**
     * Returns identifier of single storage if given document points device and it has only one
     * storage. Otherwise null.
     * Returns document IDs of storages under the given device document.
     *
     * @param documentId Document ID that may point a device.
     * @return Identifier for single storage or null.
     * @param documentId Document ID that points a device.
     * @return Storage document IDs.
     * @throws FileNotFoundException The given document ID is not registered in database.
     */
    @Nullable Identifier getSingleStorageIdentifier(String documentId)
    String[] getStorageDocumentIds(String documentId)
            throws FileNotFoundException {
        Preconditions.checkArgument(createIdentifier(documentId).mDocumentType ==
                DOCUMENT_TYPE_DEVICE);
        // Check if the parent document is device that has single storage.
        try (final Cursor cursor = mDatabase.query(
                TABLE_DOCUMENTS,
@@ -267,12 +269,11 @@ class MtpDatabase {
                null,
                null,
                null)) {
            if (cursor.getCount() == 1) {
                cursor.moveToNext();
                return createIdentifier(cursor.getString(0));
            } else {
                return null;
            final String[] ids = new String[cursor.getCount()];
            for (int i = 0; cursor.moveToNext(); i++) {
                ids[i] = cursor.getString(0);
            }
            return ids;
        }
    }

+26 −11
Original line number Diff line number Diff line
@@ -166,25 +166,25 @@ public class MtpDocumentsProvider extends DocumentsProvider {
        try {
            openDevice(parentIdentifier.mDeviceId);
            if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
                final Identifier singleStorageIdentifier =
                        mDatabase.getSingleStorageIdentifier(parentDocumentId);
                if (singleStorageIdentifier == null) {
                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);
                }
                parentIdentifier = singleStorageIdentifier;

                // 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) {
            final Bundle bundle = new Bundle();
            bundle.putString(
                    DocumentsContract.EXTRA_ERROR,
                    mResources.getString(R.string.error_busy_device));
            final Cursor cursor = new MatrixCursor(projection);
            cursor.setExtras(bundle);
            return cursor;
            return createErrorCursor(projection, R.string.error_busy_device);
        } catch (IOException exception) {
            Log.e(MtpDocumentsProvider.TAG, "queryChildDocuments", exception);
            throw new FileNotFoundException(exception.getMessage());
@@ -463,6 +463,21 @@ public class MtpDocumentsProvider extends DocumentsProvider {
        }
    }

    /**
     * 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 {
        public final PipeManager mPipeManager;
        public final DocumentLoader mDocumentLoader;
+20 −0
Original line number Diff line number Diff line
@@ -554,6 +554,26 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
        }
    }

    public void testLockedDevice() throws Exception {
        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
        mMtpManager.addValidDevice(new MtpDeviceRecord(
                0, "Device A", false /* unopened */, new MtpRoot[0], null, 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, null)) {
            assertEquals(0, cursor.getCount());
            assertEquals(
                    "error_locked_device",
                    cursor.getExtras().getString(DocumentsContract.EXTRA_ERROR));
        }
    }

    private void setupProvider(int flag) {
        mDatabase = new MtpDatabase(getContext(), flag);
        mProvider = new MtpDocumentsProvider();
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ class TestResources extends MockResources {
                return "%1$s %2$s";
            case R.string.error_busy_device:
                return "error_busy_device";
            case R.string.error_locked_device:
                return "error_locked_device";
        }
        throw new NotFoundException();
    }