diff options
6 files changed, 72 insertions, 2 deletions
diff --git a/packages/MtpDocumentsProvider/res/values/strings.xml b/packages/MtpDocumentsProvider/res/values/strings.xml index 43a420cf6d97..42bedf1c1cdc 100644 --- a/packages/MtpDocumentsProvider/res/values/strings.xml +++ b/packages/MtpDocumentsProvider/res/values/strings.xml @@ -25,4 +25,6 @@ <string name="accessing_notification_title">Accessing files from <xliff:g id="device_model" example="Nexus 9">%1$s</xliff:g></string> <!-- Description of notification showing Files app is accessing files in a MTP device. [CHAR LIMIT=60]--> <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> </resources> diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index 033845401b4b..7eae71a8d8a4 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -20,10 +20,12 @@ import android.content.ContentResolver; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.database.Cursor; +import android.database.MatrixCursor; import android.graphics.Point; import android.media.MediaFile; import android.mtp.MtpConstants; import android.mtp.MtpObjectInfo; +import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.os.storage.StorageManager; @@ -35,6 +37,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.mtp.exceptions.BusyDeviceException; import java.io.FileNotFoundException; import java.io.IOException; @@ -174,6 +177,14 @@ public class MtpDocumentsProvider extends DocumentsProvider { // 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; } catch (IOException exception) { Log.e(MtpDocumentsProvider.TAG, "queryChildDocuments", exception); throw new FileNotFoundException(exception.getMessage()); diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java index 5519efd5a323..0527790470fb 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java @@ -33,6 +33,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.mtp.exceptions.BusyDeviceException; import java.io.FileNotFoundException; import java.io.IOException; @@ -101,7 +102,8 @@ class MtpManager { } if (!device.open(connection)) { - throw new IOException("Failed to open a MTP device."); + // We cannot open connection when another application use the device. + throw new BusyDeviceException(); } // Handle devices that fail to obtain storages just after opening a MTP session. @@ -134,7 +136,7 @@ class MtpManager { try { roots = getRoots(device.getDeviceId()); } catch (IOException exp) { - Log.e(MtpDocumentsProvider.TAG, exp.getMessage()); + Log.e(MtpDocumentsProvider.TAG, "Failed to open device", exp); // If we failed to fetch roots for the device, we still returns device model // with an empty set of roots so that the device is shown DocumentsUI as long as // the device is physically connected. diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java new file mode 100644 index 000000000000..55f55b0edbc3 --- /dev/null +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 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.exceptions; + +import java.io.IOException; + +/** + * Exception thrown when the device is busy and the requested operation cannon be completed. + */ +public class BusyDeviceException extends IOException { +} diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index 5b0f55703a2b..4bc016247762 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -29,6 +29,8 @@ import android.provider.DocumentsContract; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; +import com.android.mtp.exceptions.BusyDeviceException; + import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; @@ -526,6 +528,32 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { } } + public void testBusyDevice() throws Exception { + mMtpManager = new TestMtpManager(getContext()) { + @Override + void openDevice(int deviceId) throws IOException { + throw new BusyDeviceException(); + } + }; + 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_busy_device", + cursor.getExtras().getString(DocumentsContract.EXTRA_ERROR)); + } + } + private void setupProvider(int flag) { mDatabase = new MtpDatabase(getContext(), flag); mProvider = new MtpDocumentsProvider(); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java index b23038b6c3f6..a576a04ac6bb 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java @@ -24,6 +24,8 @@ class TestResources extends MockResources { switch (id) { case R.string.root_name: return "%1$s %2$s"; + case R.string.error_busy_device: + return "error_busy_device"; } throw new NotFoundException(); } |