diff options
7 files changed, 134 insertions, 28 deletions
diff --git a/api/current.xml b/api/current.xml index 5592759..8573a36 100644 --- a/api/current.xml +++ b/api/current.xml @@ -119461,6 +119461,17 @@ visibility="public" > </field> +<field name="OperationFailedStorageBusy" + type="int" + transient="false" + volatile="false" + value="-7" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OperationFailedStorageMounted" type="int" transient="false" diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl index 816baf3..79a6cfe 100644 --- a/core/java/android/os/storage/IMountService.aidl +++ b/core/java/android/os/storage/IMountService.aidl @@ -63,7 +63,7 @@ interface IMountService * Safely unmount external storage at given mount point. * Returns an int consistent with MountServiceResultCode */ - int unmountVolume(String mountPoint); + int unmountVolume(String mountPoint, boolean force); /** * Format external storage given a mount point. @@ -100,7 +100,7 @@ interface IMountService * NOTE: Ensure all references are released prior to deleting. * Returns an int consistent with MountServiceResultCode */ - int destroySecureContainer(String id); + int destroySecureContainer(String id, boolean force); /* * Mount a secure container with the specified key and owner UID. @@ -112,7 +112,7 @@ interface IMountService * Unount a secure container. * Returns an int consistent with MountServiceResultCode */ - int unmountSecureContainer(String id); + int unmountSecureContainer(String id, boolean force); /* * Returns true if the specified container is mounted diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java index 249bacf..07d95df 100644 --- a/core/java/android/os/storage/StorageResultCode.java +++ b/core/java/android/os/storage/StorageResultCode.java @@ -64,4 +64,10 @@ public class StorageResultCode */ public static final int OperationFailedStorageMounted = -6; + /** + * Operation failed: Storage is busy. + * @see android.os.storage.StorageManager + */ + public static final int OperationFailedStorageBusy = -7; + } diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index c5b869b..bc7dbf4 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -93,7 +93,7 @@ public class PackageHelper { public static boolean unMountSdDir(String cid) { try { - int rc = getMountService().unmountSecureContainer(cid); + int rc = getMountService().unmountSecureContainer(cid, false); if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc); return false; @@ -148,7 +148,7 @@ public class PackageHelper { public static boolean destroySdDir(String cid) { try { - int rc = getMountService().destroySecureContainer(cid); + int rc = getMountService().destroySecureContainer(cid, false); if (rc != StorageResultCode.OperationSucceeded) { Log.i(TAG, "Failed to destroy container " + cid); return false; diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 4e2ffa4..ad377e3 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -97,7 +97,7 @@ class MountService extends IMountService.Stub public static final int OpFailedMediaBlank = 402; public static final int OpFailedMediaCorrupt = 403; public static final int OpFailedVolNotMounted = 404; - public static final int OpFailedVolBusy = 405; + public static final int OpFailedStorageBusy = 405; /* * 600 series - Unsolicited broadcasts. @@ -184,7 +184,7 @@ class MountService extends IMountService.Stub String vs = getVolumeState(path); if (enable && vs.equals(Environment.MEDIA_MOUNTED)) { mUmsEnabling = enable; // Override for isUsbMassStorageEnabled() - int rc = doUnmountVolume(path); + int rc = doUnmountVolume(path, false); mUmsEnabling = false; // Clear override if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, String.format("Failed to unmount before enabling UMS (%d)", rc)); @@ -527,7 +527,7 @@ class MountService extends IMountService.Stub return rc; } - private int doUnmountVolume(String path) { + private int doUnmountVolume(String path, boolean force) { if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) { return VoldResponseCode.OpFailedVolNotMounted; } @@ -537,7 +537,8 @@ class MountService extends IMountService.Stub // notified that the applications installed on the media will be killed. mPms.updateExternalMediaStatus(false); try { - mConnector.doCommand(String.format("volume unmount %s", path)); + mConnector.doCommand(String.format( + "volume unmount %s%s", path, (force ? " force" : ""))); return StorageResultCode.OperationSucceeded; } catch (NativeDaemonConnectorException e) { // Don't worry about mismatch in PackageManager since the @@ -545,6 +546,8 @@ class MountService extends IMountService.Stub int code = e.getCode(); if (code == VoldResponseCode.OpFailedVolNotMounted) { return StorageResultCode.OperationFailedStorageNotMounted; + } else if (code == VoldResponseCode.OpFailedStorageBusy) { + return StorageResultCode.OperationFailedStorageBusy; } else { return StorageResultCode.OperationFailedInternalError; } @@ -733,7 +736,7 @@ class MountService extends IMountService.Stub /* * If the media is mounted, then gracefully unmount it. */ - if (doUnmountVolume(path) != StorageResultCode.OperationSucceeded) { + if (doUnmountVolume(path, true) != StorageResultCode.OperationSucceeded) { Log.e(TAG, "Failed to unmount media for shutdown"); } } @@ -782,11 +785,11 @@ class MountService extends IMountService.Stub return doMountVolume(path); } - public int unmountVolume(String path) { + public int unmountVolume(String path, boolean force) { validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); - return doUnmountVolume(path); + return doUnmountVolume(path, force); } public int formatVolume(String path) { @@ -878,16 +881,21 @@ class MountService extends IMountService.Stub return rc; } - public int destroySecureContainer(String id) { + public int destroySecureContainer(String id, boolean force) { validatePermission(android.Manifest.permission.ASEC_DESTROY); waitForReady(); warnOnNotMounted(); int rc = StorageResultCode.OperationSucceeded; try { - mConnector.doCommand(String.format("asec destroy %s", id)); + mConnector.doCommand(String.format("asec destroy %s%s", id, (force ? " force" : ""))); } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; + int code = e.getCode(); + if (code == VoldResponseCode.OpFailedStorageBusy) { + rc = StorageResultCode.OperationFailedStorageBusy; + } else { + rc = StorageResultCode.OperationFailedInternalError; + } } if (rc == StorageResultCode.OperationSucceeded) { @@ -928,7 +936,7 @@ class MountService extends IMountService.Stub return rc; } - public int unmountSecureContainer(String id) { + public int unmountSecureContainer(String id, boolean force) { validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT); waitForReady(); warnOnNotMounted(); @@ -940,11 +948,16 @@ class MountService extends IMountService.Stub } int rc = StorageResultCode.OperationSucceeded; - String cmd = String.format("asec unmount %s", id); + String cmd = String.format("asec unmount %s%s", id, (force ? " force" : "")); try { mConnector.doCommand(cmd); } catch (NativeDaemonConnectorException e) { - rc = StorageResultCode.OperationFailedInternalError; + int code = e.getCode(); + if (code == VoldResponseCode.OpFailedStorageBusy) { + rc = StorageResultCode.OperationFailedStorageBusy; + } else { + rc = StorageResultCode.OperationFailedInternalError; + } } if (rc == StorageResultCode.OperationSucceeded) { diff --git a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java index 7569d7a..bdf397c 100755 --- a/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/AsecTests.java @@ -73,7 +73,7 @@ public class AsecTests extends AndroidTestCase { for (int i = 0; i < containers.length; i++) { if (containers[i].startsWith("com.android.unittests.AsecTests.")) { - ms.destroySecureContainer(containers[i]); + ms.destroySecureContainer(containers[i], true); } } } @@ -103,7 +103,32 @@ public class AsecTests extends AndroidTestCase { Assert.assertTrue(isMediaMounted()); IMountService ms = getMs(); try { - int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateContainer", 4, "fat", "none", 1000); + int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateContainer", + 4, "fat", "none", android.os.Process.myUid()); + Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); + } catch (Exception e) { + failStr(e); + } + } + + public void testCreateZeroSizeContainer() { + Assert.assertTrue(isMediaMounted()); + IMountService ms = getMs(); + try { + int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateZeroSizeContainer", + 0, "fat", "none", android.os.Process.myUid()); + Assert.assertEquals(StorageResultCode.OperationFailedInternalError, rc); + } catch (Exception e) { + failStr(e); + } + } + + public void testCreateMinSizeContainer() { + Assert.assertTrue(isMediaMounted()); + IMountService ms = getMs(); + try { + int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testCreateMinSizeContainer", + 1, "fat", "none", android.os.Process.myUid()); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); } catch (Exception e) { failStr(e); @@ -114,9 +139,10 @@ public class AsecTests extends AndroidTestCase { Assert.assertTrue(isMediaMounted()); IMountService ms = getMs(); try { - int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testDestroyContainer", 4, "fat", "none", 1000); + int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testDestroyContainer", + 4, "fat", "none", android.os.Process.myUid()); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); - rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testDestroyContainer"); + rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testDestroyContainer", true); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); } catch (Exception e) { failStr(e); @@ -128,13 +154,15 @@ public class AsecTests extends AndroidTestCase { IMountService ms = getMs(); try { int rc = ms.createSecureContainer( - "com.android.unittests.AsecTests.testMountContainer", 4, "fat", "none", 1000); + "com.android.unittests.AsecTests.testMountContainer", + 4, "fat", "none", android.os.Process.myUid()); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); - rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountContainer"); + rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountContainer", false); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); - rc = ms.mountSecureContainer("com.android.unittests.AsecTests.testMountContainer", "none", 1000); + rc = ms.mountSecureContainer("com.android.unittests.AsecTests.testMountContainer", "none", + android.os.Process.myUid()); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); } catch (Exception e) { failStr(e); @@ -147,10 +175,10 @@ public class AsecTests extends AndroidTestCase { try { int rc = ms.createSecureContainer( "com.android.unittests.AsecTests.testMountBadKey", 4, "fat", - "00000000000000000000000000000000", 1000); + "00000000000000000000000000000000", android.os.Process.myUid()); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); - rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountBadKey"); + rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testMountBadKey", false); Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); rc = ms.mountSecureContainer( @@ -165,4 +193,52 @@ public class AsecTests extends AndroidTestCase { failStr(e); } } + + public void testUnmountBusyContainer() { + Assert.assertTrue(isMediaMounted()); + IMountService ms = getMs(); + try { + int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", + 4, "fat", "none", android.os.Process.myUid()); + Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); + + String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer"); + Context con = super.getContext(); + + File f = new File(path, "reference"); + FileOutputStream fos = new FileOutputStream(f); + rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false); + Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, rc); + fos.close(); + + rc = ms.unmountSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false); + Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); + } catch (Exception e) { + failStr(e); + } + } + + public void testDestroyBusyContainer() { + Assert.assertTrue(isMediaMounted()); + IMountService ms = getMs(); + try { + int rc = ms.createSecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", + 4, "fat", "none", android.os.Process.myUid()); + Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); + + String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer"); + Context con = super.getContext(); + + File f = new File(path, "reference"); + FileOutputStream fos = new FileOutputStream(f); + rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false); + Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy, rc); + fos.close(); + + rc = ms.destroySecureContainer("com.android.unittests.AsecTests.testUnmountBusyContainer", false); + Assert.assertEquals(StorageResultCode.OperationSucceeded, rc); + } catch (Exception e) { + failStr(e); + } + } } diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java index 8f4d0a1..be9571c 100755 --- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java +++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java @@ -716,7 +716,7 @@ public class PackageManagerTests extends AndroidTestCase { } try { String mPath = Environment.getExternalStorageDirectory().toString(); - int ret = getMs().unmountVolume(mPath); + int ret = getMs().unmountVolume(mPath, false); return ret == StorageResultCode.OperationSucceeded; } catch (RemoteException e) { return true; |