diff options
7 files changed, 43 insertions, 23 deletions
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index e0130b5cd069..d1dc6e578b82 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -169,13 +169,15 @@ public interface IMountService extends IInterface { * is an asynchronous operation. Applications should register * StorageEventListener for storage related status changes. */ - public void unmountVolume(String mountPoint, boolean force) throws RemoteException { + public void unmountVolume(String mountPoint, boolean force, boolean removeEncryption) + throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(mountPoint); _data.writeInt((force ? 1 : 0)); + _data.writeInt((removeEncryption ? 1 : 0)); mRemote.transact(Stub.TRANSACTION_unmountVolume, _data, _reply, 0); _reply.readException(); } finally { @@ -842,9 +844,9 @@ public interface IMountService extends IInterface { data.enforceInterface(DESCRIPTOR); String mountPoint; mountPoint = data.readString(); - boolean force; - force = 0 != data.readInt(); - unmountVolume(mountPoint, force); + boolean force = 0 != data.readInt(); + boolean removeEncrypt = 0 != data.readInt(); + unmountVolume(mountPoint, force, removeEncrypt); reply.writeNoException(); return true; } @@ -1234,8 +1236,14 @@ public interface IMountService extends IInterface { * Safely unmount external storage at given mount point. The unmount is an * asynchronous operation. Applications should register StorageEventListener * for storage related status changes. + * @param mountPoint the mount point + * @param force whether or not to forcefully unmount it (e.g. even if programs are using this + * data currently) + * @param removeEncryption whether or not encryption mapping should be removed from the volume. + * This value implies {@code force}. */ - public void unmountVolume(String mountPoint, boolean force) throws RemoteException; + public void unmountVolume(String mountPoint, boolean force, boolean removeEncryption) + throws RemoteException; /** * Unregisters an IMountServiceListener diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java index 4773ce4b6add..3905c88ac282 100644 --- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java +++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java @@ -152,7 +152,8 @@ public class ExternalStorageFormatter extends Service Environment.getExternalStorageDirectory().toString() : mStorageVolume.getPath(); try { - mountService.unmountVolume(extStoragePath, true); + // Remove encryption mapping if this is an unmount for a factory reset. + mountService.unmountVolume(extStoragePath, true, mFactoryReset); } catch (RemoteException e) { Log.w(TAG, "Failed talking with mount service", e); } diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 6c87c3b7c47a..68ddcc4b7af8 100755 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -1057,7 +1057,7 @@ public class PackageManagerTests extends AndroidTestCase { try { // Wait on observer synchronized(observer) { - getMs().unmountVolume(path, true); + getMs().unmountVolume(path, true, false); long waitTime = 0; while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { observer.wait(WAIT_TIME_INCR); diff --git a/core/tests/coretests/src/android/os/storage/AsecTests.java b/core/tests/coretests/src/android/os/storage/AsecTests.java index dda301090c91..5efbd8853060 100755 --- a/core/tests/coretests/src/android/os/storage/AsecTests.java +++ b/core/tests/coretests/src/android/os/storage/AsecTests.java @@ -421,7 +421,7 @@ public class AsecTests extends AndroidTestCase { try { // Wait on observer synchronized(observer) { - getMs().unmountVolume(path, false); + getMs().unmountVolume(path, false, false); long waitTime = 0; while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { observer.wait(WAIT_TIME_INCR); @@ -486,7 +486,7 @@ public class AsecTests extends AndroidTestCase { // Wait on observer synchronized(observer) { for (int i = 0; i < 5; i++) { - getMs().unmountVolume(path, false); + getMs().unmountVolume(path, false, false); } long waitTime = 0; while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) { diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h index 472d8e502f73..43df7f06f4d4 100644 --- a/include/storage/IMountService.h +++ b/include/storage/IMountService.h @@ -37,8 +37,8 @@ public: virtual void setUsbMassStorageEnabled(const bool enable) = 0; virtual bool isUsbMassStorageEnabled() = 0; virtual int32_t mountVolume(const String16& mountPoint) = 0; - virtual int32_t - unmountVolume(const String16& mountPoint, const bool force) = 0; + virtual int32_t unmountVolume( + const String16& mountPoint, const bool force, const bool removeEncryption) = 0; virtual int32_t formatVolume(const String16& mountPoint) = 0; virtual int32_t getStorageUsers(const String16& mountPoint, int32_t** users) = 0; diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp index 7fbf67a02764..8ddbeaedcfb4 100644 --- a/libs/storage/IMountService.cpp +++ b/libs/storage/IMountService.cpp @@ -157,12 +157,13 @@ public: return reply.readInt32(); } - int32_t unmountVolume(const String16& mountPoint, const bool force) + int32_t unmountVolume(const String16& mountPoint, const bool force, const bool removeEncryption) { Parcel data, reply; data.writeInterfaceToken(IMountService::getInterfaceDescriptor()); data.writeString16(mountPoint); data.writeInt32(force ? 1 : 0); + data.writeInt32(removeEncryption ? 1 : 0); if (remote()->transact(TRANSACTION_unmountVolume, data, &reply) != NO_ERROR) { LOGD("unmountVolume could not contact remote\n"); return -1; diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index d806309cd34f..582f0ede6c63 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -304,17 +304,19 @@ class MountService extends IMountService.Stub class UnmountCallBack { final String path; final boolean force; + final boolean removeEncryption; int retries; - UnmountCallBack(String path, boolean force) { + UnmountCallBack(String path, boolean force, boolean removeEncryption) { retries = 0; this.path = path; this.force = force; + this.removeEncryption = removeEncryption; } void handleFinished() { if (DEBUG_UNMOUNT) Slog.i(TAG, "Unmounting " + path); - doUnmountVolume(path, true); + doUnmountVolume(path, true, removeEncryption); } } @@ -322,7 +324,7 @@ class MountService extends IMountService.Stub final String method; UmsEnableCallBack(String path, String method, boolean force) { - super(path, force); + super(path, force, false); this.method = method; } @@ -336,13 +338,13 @@ class MountService extends IMountService.Stub class ShutdownCallBack extends UnmountCallBack { IMountShutdownObserver observer; ShutdownCallBack(String path, IMountShutdownObserver observer) { - super(path, true); + super(path, true, false); this.observer = observer; } @Override void handleFinished() { - int ret = doUnmountVolume(path, true); + int ret = doUnmountVolume(path, true, removeEncryption); if (observer != null) { try { observer.onShutDownComplete(ret); @@ -888,8 +890,10 @@ class MountService extends IMountService.Stub * This might even take a while and might be retried after timed delays * to make sure we dont end up in an instable state and kill some core * processes. + * If removeEncryption is set, force is implied, and the system will remove any encryption + * mapping set on the volume when unmounting. */ - private int doUnmountVolume(String path, boolean force) { + private int doUnmountVolume(String path, boolean force, boolean removeEncryption) { if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) { return VoldResponseCode.OpFailedVolNotMounted; } @@ -905,8 +909,10 @@ class MountService extends IMountService.Stub // Redundant probably. But no harm in updating state again. mPms.updateExternalMediaStatus(false, false); try { - mConnector.doCommand(String.format( - "volume unmount %s%s", path, (force ? " force" : ""))); + String arg = removeEncryption + ? " force_and_revert" + : (force ? " force" : ""); + mConnector.doCommand(String.format("volume unmount %s%s", path, arg)); // We unmounted the volume. None of the asec containers are available now. synchronized (mAsecMountSet) { mAsecMountSet.clear(); @@ -1371,12 +1377,16 @@ class MountService extends IMountService.Stub return doMountVolume(path); } - public void unmountVolume(String path, boolean force) { + public void unmountVolume(String path, boolean force, boolean removeEncryption) { validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); String volState = getVolumeState(path); - if (DEBUG_UNMOUNT) Slog.i(TAG, "Unmounting " + path + " force = " + force); + if (DEBUG_UNMOUNT) { + Slog.i(TAG, "Unmounting " + path + + " force = " + force + + " removeEncryption = " + removeEncryption); + } if (Environment.MEDIA_UNMOUNTED.equals(volState) || Environment.MEDIA_REMOVED.equals(volState) || Environment.MEDIA_SHARED.equals(volState) || @@ -1385,7 +1395,7 @@ class MountService extends IMountService.Stub // TODO return valid return code when adding observer call back. return; } - UnmountCallBack ucb = new UnmountCallBack(path, force); + UnmountCallBack ucb = new UnmountCallBack(path, force, removeEncryption); mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb)); } |