summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/MountService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/MountService.java')
-rw-r--r--services/java/com/android/server/MountService.java555
1 files changed, 321 insertions, 234 deletions
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 6382646..456244a 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -23,29 +23,34 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
-import android.os.IMountService;
-import android.os.IMountServiceListener;
-import android.os.MountServiceResultCode;
+import android.os.storage.IMountService;
+import android.os.storage.IMountServiceListener;
+import android.os.storage.StorageResultCode;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Environment;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
+import java.util.HashSet;
import java.io.File;
import java.io.FileReader;
/**
- * MountService implements an to the mount service daemon
- * @hide
+ * MountService implements back-end services for platform storage
+ * management.
+ * @hide - Applications should use android.os.storage.StorageManager
+ * to access the MountService.
*/
class MountService extends IMountService.Stub
implements INativeDaemonConnectorCallbacks {
+ private static final boolean LOCAL_LOGD = false;
private static final String TAG = "MountService";
@@ -109,45 +114,40 @@ class MountService extends IMountService.Stub
private PackageManagerService mPms;
private boolean mUmsEnabling;
private ArrayList<MountServiceBinderListener> mListeners;
+ private boolean mBooted;
+ private boolean mReady;
/**
- * Constructs a new MountService instance
- *
- * @param context Binder context for this service
+ * Private hash of currently mounted secure containers.
*/
- public MountService(Context context) {
- mContext = context;
-
- // XXX: This will go away soon in favor of IMountServiceObserver
- mPms = (PackageManagerService) ServiceManager.getService("package");
-
- // Register a BOOT_COMPLETED handler so that we can start
- // our NativeDaemonConnector. We defer the startup so that we don't
- // start processing events before we ought-to
- mContext.registerReceiver(mBroadcastReceiver,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ private HashSet<String> mAsecMountSet = new HashSet<String>();
- mConnector = new NativeDaemonConnector(this, "vold", 10, "VoldConnector");
- mListeners = new ArrayList<MountServiceBinderListener>();
+ private void waitForReady() {
+ while (mReady == false) {
+ for (int retries = 5; retries > 0; retries--) {
+ if (mReady) {
+ return;
+ }
+ SystemClock.sleep(1000);
+ }
+ Log.w(TAG, "Waiting too long for mReady!");
+ }
}
- BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- /*
- * Vold does not run in the simulator, so fake out a mounted
- * event to trigger MediaScanner
- */
- if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
- updatePublicVolumeState("/sdcard", Environment.MEDIA_MOUNTED);
- return;
- }
+ mBooted = true;
- Thread thread = new Thread(
- mConnector, NativeDaemonConnector.class.getName());
- thread.start();
+ String path = Environment.getExternalStorageDirectory().getPath();
+ if (getVolumeState(path).equals(Environment.MEDIA_UNMOUNTED)) {
+ int rc = doMountVolume(path);
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Boot-time mount failed (%d)", rc));
+ }
+ }
}
}
};
@@ -161,7 +161,7 @@ class MountService extends IMountService.Stub
}
public void binderDied() {
- Log.d(TAG, "An IMountServiceListener has died!");
+ if (LOCAL_LOGD) Log.d(TAG, "An IMountServiceListener has died!");
synchronized(mListeners) {
mListeners.remove(this);
mListener.asBinder().unlinkToDeath(this, 0);
@@ -169,7 +169,7 @@ class MountService extends IMountService.Stub
}
}
- int doShareUnshareVolume(String path, String method, boolean enable) {
+ private int doShareUnshareVolume(String path, String method, boolean enable) {
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
// TODO: Add support for multiple share methods
@@ -182,9 +182,13 @@ class MountService extends IMountService.Stub
*/
String vs = getVolumeState(path);
if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
- mUmsEnabling = enable; // Supress unmounted events
- unmountVolume(path);
- mUmsEnabling = false; // Unsupress unmounted events
+ mUmsEnabling = enable; // Override for isUsbMassStorageEnabled()
+ int rc = doUnmountVolume(path);
+ mUmsEnabling = false; // Clear override
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Failed to unmount before enabling UMS (%d)", rc));
+ return rc;
+ }
}
try {
@@ -192,14 +196,14 @@ class MountService extends IMountService.Stub
"volume %sshare %s %s", (enable ? "" : "un"), path, method));
} catch (NativeDaemonConnectorException e) {
Log.e(TAG, "Failed to share/unshare", e);
- return MountServiceResultCode.OperationFailedInternalError;
+ return StorageResultCode.OperationFailedInternalError;
}
/*
* If we disabled UMS then mount the volume
*/
if (!enable) {
- if (mountVolume(path) != MountServiceResultCode.OperationSucceeded) {
+ if (doMountVolume(path) != StorageResultCode.OperationSucceeded) {
Log.e(TAG, String.format(
"Failed to remount %s after disabling share method %s", path, method));
/*
@@ -210,15 +214,19 @@ class MountService extends IMountService.Stub
}
}
- return MountServiceResultCode.OperationSucceeded;
+ return StorageResultCode.OperationSucceeded;
}
- void updatePublicVolumeState(String path, String state) {
+ private void updatePublicVolumeState(String path, String state) {
if (!path.equals(Environment.getExternalStorageDirectory().getPath())) {
Log.w(TAG, "Multiple volumes not currently supported");
return;
}
- Log.i(TAG, "State for {" + path + "} = {" + state + "}");
+
+ if (mLegacyState.equals(state)) {
+ Log.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
+ return;
+ }
String oldState = mLegacyState;
mLegacyState = state;
@@ -227,7 +235,7 @@ class MountService extends IMountService.Stub
for (int i = mListeners.size() -1; i >= 0; i--) {
MountServiceBinderListener bl = mListeners.get(i);
try {
- bl.mListener.onVolumeStateChanged("", path, oldState, state);
+ bl.mListener.onStorageStateChanged(path, oldState, state);
} catch (RemoteException rex) {
Log.e(TAG, "Listener dead");
mListeners.remove(i);
@@ -270,11 +278,7 @@ class MountService extends IMountService.Stub
if (st == VolumeState.NoMedia) {
state = Environment.MEDIA_REMOVED;
} else if (st == VolumeState.Idle) {
- state = null;
- int rc = mountVolume(path);
- if (rc != MountServiceResultCode.OperationSucceeded) {
- Log.e(TAG, String.format("Connection-mount failed (%d)", rc));
- }
+ state = Environment.MEDIA_UNMOUNTED;
} else if (st == VolumeState.Mounted) {
state = Environment.MEDIA_MOUNTED;
Log.i(TAG, "Media already mounted on daemon connection");
@@ -294,23 +298,26 @@ class MountService extends IMountService.Stub
}
try {
- boolean avail = getShareMethodAvailable("ums");
+ boolean avail = doGetShareMethodAvailable("ums");
notifyShareAvailabilityChange("ums", avail);
} catch (Exception ex) {
Log.w(TAG, "Failed to get share availability");
}
+ /*
+ * Now that we've done our initialization, release
+ * the hounds!
+ */
+ mReady = true;
}
}.start();
}
/**
- *
* Callback from NativeDaemonConnector
*/
public boolean onEvent(int code, String raw, String[] cooked) {
Intent in = null;
- // Log.d(TAG, "event {" + raw + "}");
if (code == VoldResponseCode.VolumeStateChange) {
/*
* One of the volumes we're managing has changed state.
@@ -347,34 +354,12 @@ class MountService extends IMountService.Stub
Log.e(TAG, "Failed to parse major/minor", ex);
}
- synchronized (mListeners) {
- for (int i = mListeners.size() -1; i >= 0; i--) {
- MountServiceBinderListener bl = mListeners.get(i);
- try {
- if (code == VoldResponseCode.VolumeDiskInserted) {
- bl.mListener.onMediaInserted(label, path, major, minor);
- } else if (code == VoldResponseCode.VolumeDiskRemoved) {
- bl.mListener.onMediaRemoved(label, path, major, minor, true);
- } else if (code == VoldResponseCode.VolumeBadRemoval) {
- bl.mListener.onMediaRemoved(label, path, major, minor, false);
- } else {
- Log.e(TAG, String.format("Unknown code {%d}", code));
- }
- } catch (RemoteException rex) {
- Log.e(TAG, "Listener dead");
- mListeners.remove(i);
- } catch (Exception ex) {
- Log.e(TAG, "Listener failed", ex);
- }
- }
- }
-
if (code == VoldResponseCode.VolumeDiskInserted) {
new Thread() {
public void run() {
try {
int rc;
- if ((rc = mountVolume(path)) != MountServiceResultCode.OperationSucceeded) {
+ if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
Log.w(TAG, String.format("Insertion mount failed (%d)", rc));
}
} catch (Exception ex) {
@@ -417,7 +402,7 @@ class MountService extends IMountService.Stub
return true;
}
- void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
+ private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
String vs = getVolumeState(path);
Intent in = null;
@@ -471,7 +456,144 @@ class MountService extends IMountService.Stub
}
}
- void notifyShareAvailabilityChange(String method, final boolean avail) {
+ private boolean doGetShareMethodAvailable(String method) {
+ ArrayList<String> rsp = mConnector.doCommand("share status " + method);
+
+ for (String line : rsp) {
+ String []tok = line.split(" ");
+ int code;
+ try {
+ code = Integer.parseInt(tok[0]);
+ } catch (NumberFormatException nfe) {
+ Log.e(TAG, String.format("Error parsing code %s", tok[0]));
+ return false;
+ }
+ if (code == VoldResponseCode.ShareStatusResult) {
+ if (tok[2].equals("available"))
+ return true;
+ return false;
+ } else {
+ Log.e(TAG, String.format("Unexpected response code %d", code));
+ return false;
+ }
+ }
+ Log.e(TAG, "Got an empty response");
+ return false;
+ }
+
+ private int doMountVolume(String path) {
+ int rc = StorageResultCode.OperationSucceeded;
+
+ try {
+ mConnector.doCommand(String.format("volume mount %s", path));
+ } catch (NativeDaemonConnectorException e) {
+ /*
+ * Mount failed for some reason
+ */
+ Intent in = null;
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedNoMedia) {
+ /*
+ * Attempt to mount but no media inserted
+ */
+ rc = StorageResultCode.OperationFailedNoMedia;
+ } else if (code == VoldResponseCode.OpFailedMediaBlank) {
+ /*
+ * Media is blank or does not contain a supported filesystem
+ */
+ updatePublicVolumeState(path, Environment.MEDIA_NOFS);
+ in = new Intent(Intent.ACTION_MEDIA_NOFS, Uri.parse("file://" + path));
+ rc = StorageResultCode.OperationFailedMediaBlank;
+ } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
+ /*
+ * Volume consistency check failed
+ */
+ updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
+ in = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE, Uri.parse("file://" + path));
+ rc = StorageResultCode.OperationFailedMediaCorrupt;
+ } else {
+ rc = StorageResultCode.OperationFailedInternalError;
+ }
+
+ /*
+ * Send broadcast intent (if required for the failure)
+ */
+ if (in != null) {
+ mContext.sendBroadcast(in);
+ }
+ }
+
+ return rc;
+ }
+
+ private int doUnmountVolume(String path) {
+ if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) {
+ return VoldResponseCode.OpFailedVolNotMounted;
+ }
+
+ // Notify PackageManager of potential media removal and deal with
+ // return code later on. The caller of this api should be aware or have been
+ // notified that the applications installed on the media will be killed.
+ mPms.updateExternalMediaStatus(false);
+ try {
+ mConnector.doCommand(String.format("volume unmount %s", path));
+ return StorageResultCode.OperationSucceeded;
+ } catch (NativeDaemonConnectorException e) {
+ // Don't worry about mismatch in PackageManager since the
+ // call back will handle the status changes any way.
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedVolNotMounted) {
+ return StorageResultCode.OperationFailedVolumeNotMounted;
+ } else {
+ return StorageResultCode.OperationFailedInternalError;
+ }
+ }
+ }
+
+ private int doFormatVolume(String path) {
+ try {
+ String cmd = String.format("volume format %s", path);
+ mConnector.doCommand(cmd);
+ return StorageResultCode.OperationSucceeded;
+ } catch (NativeDaemonConnectorException e) {
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedNoMedia) {
+ return StorageResultCode.OperationFailedNoMedia;
+ } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
+ return StorageResultCode.OperationFailedMediaCorrupt;
+ } else {
+ return StorageResultCode.OperationFailedInternalError;
+ }
+ }
+ }
+
+ private boolean doGetVolumeShared(String path, String method) {
+ String cmd = String.format("volume shared %s %s", path, method);
+ ArrayList<String> rsp = mConnector.doCommand(cmd);
+
+ for (String line : rsp) {
+ String []tok = line.split(" ");
+ int code;
+ try {
+ code = Integer.parseInt(tok[0]);
+ } catch (NumberFormatException nfe) {
+ Log.e(TAG, String.format("Error parsing code %s", tok[0]));
+ return false;
+ }
+ if (code == VoldResponseCode.ShareEnabledResult) {
+ if (tok[2].equals("enabled"))
+ return true;
+ return false;
+ } else {
+ Log.e(TAG, String.format("Unexpected response code %d", code));
+ return false;
+ }
+ }
+ Log.e(TAG, "Got an empty response");
+ return false;
+ }
+
+ private void notifyShareAvailabilityChange(String method, final boolean avail) {
if (!method.equals("ums")) {
Log.w(TAG, "Ignoring unsupported share method {" + method + "}");
return;
@@ -481,7 +603,7 @@ class MountService extends IMountService.Stub
for (int i = mListeners.size() -1; i >= 0; i--) {
MountServiceBinderListener bl = mListeners.get(i);
try {
- bl.mListener.onShareAvailabilityChanged(method, avail);
+ bl.mListener.onUsbMassStorageConnectionChanged(avail);
} catch (RemoteException rex) {
Log.e(TAG, "Listener dead");
mListeners.remove(i);
@@ -491,22 +613,55 @@ class MountService extends IMountService.Stub
}
}
- Intent intent;
- if (avail) {
- intent = new Intent(Intent.ACTION_UMS_CONNECTED);
- } else {
- intent = new Intent(Intent.ACTION_UMS_DISCONNECTED);
+ if (mBooted == true) {
+ Intent intent;
+ if (avail) {
+ intent = new Intent(Intent.ACTION_UMS_CONNECTED);
+ } else {
+ intent = new Intent(Intent.ACTION_UMS_DISCONNECTED);
+ }
+ mContext.sendBroadcast(intent);
}
- mContext.sendBroadcast(intent);
}
- void validatePermission(String perm) {
+ private void validatePermission(String perm) {
if (mContext.checkCallingOrSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(String.format("Requires %s permission", perm));
}
}
/**
+ * Constructs a new MountService instance
+ *
+ * @param context Binder context for this service
+ */
+ public MountService(Context context) {
+ mContext = context;
+
+ /*
+ * Vold does not run in the simulator, so fake out a mounted
+ * event to trigger MediaScanner
+ */
+ if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
+ updatePublicVolumeState("/sdcard", Environment.MEDIA_MOUNTED);
+ return;
+ }
+
+ // XXX: This will go away soon in favor of IMountServiceObserver
+ mPms = (PackageManagerService) ServiceManager.getService("package");
+
+ mContext.registerReceiver(mBroadcastReceiver,
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+
+ mListeners = new ArrayList<MountServiceBinderListener>();
+
+ mConnector = new NativeDaemonConnector(this, "vold", 10, "VoldConnector");
+ mReady = false;
+ Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
+ thread.start();
+ }
+
+ /**
* Exposed API calls below here
*/
@@ -549,7 +704,7 @@ class MountService extends IMountService.Stub
* the UMS host could have dirty FAT cache entries
* yet to flush.
*/
- if (unshareVolume(path, "ums") != MountServiceResultCode.OperationSucceeded) {
+ if (setUsbMassStorageEnabled(false) != StorageResultCode.OperationSucceeded) {
Log.e(TAG, "UMS disable on shutdown failed");
}
} else if (state.equals(Environment.MEDIA_CHECKING)) {
@@ -577,75 +732,30 @@ class MountService extends IMountService.Stub
/*
* If the media is mounted, then gracefully unmount it.
*/
- if (unmountVolume(path) != MountServiceResultCode.OperationSucceeded) {
+ if (doUnmountVolume(path) != StorageResultCode.OperationSucceeded) {
Log.e(TAG, "Failed to unmount media for shutdown");
}
}
}
- public String[] getShareMethodList() {
- String[] rdata = new String[1];
- rdata[0] = "ums";
- return rdata;
- }
+ public boolean isUsbMassStorageConnected() {
+ waitForReady();
- public boolean getShareMethodAvailable(String method) {
- ArrayList<String> rsp = mConnector.doCommand("share status " + method);
-
- for (String line : rsp) {
- String []tok = line.split(" ");
- int code;
- try {
- code = Integer.parseInt(tok[0]);
- } catch (NumberFormatException nfe) {
- Log.e(TAG, String.format("Error parsing code %s", tok[0]));
- return false;
- }
- if (code == VoldResponseCode.ShareStatusResult) {
- if (tok[2].equals("available"))
- return true;
- return false;
- } else {
- Log.e(TAG, String.format("Unexpected response code %d", code));
- return false;
- }
+ if (mUmsEnabling) {
+ return true;
}
- Log.e(TAG, "Got an empty response");
- return false;
+ return doGetShareMethodAvailable("ums");
}
- public int shareVolume(String path, String method) {
- return doShareUnshareVolume(path, method, true);
- }
+ public int setUsbMassStorageEnabled(boolean enable) {
+ waitForReady();
- public int unshareVolume(String path, String method) {
- return doShareUnshareVolume(path, method, false);
+ return doShareUnshareVolume(Environment.getExternalStorageDirectory().getPath(), "ums", enable);
}
- public boolean getVolumeShared(String path, String method) {
- String cmd = String.format("volume shared %s %s", path, method);
- ArrayList<String> rsp = mConnector.doCommand(cmd);
-
- for (String line : rsp) {
- String []tok = line.split(" ");
- int code;
- try {
- code = Integer.parseInt(tok[0]);
- } catch (NumberFormatException nfe) {
- Log.e(TAG, String.format("Error parsing code %s", tok[0]));
- return false;
- }
- if (code == VoldResponseCode.ShareEnabledResult) {
- if (tok[2].equals("enabled"))
- return true;
- return false;
- } else {
- Log.e(TAG, String.format("Unexpected response code %d", code));
- return false;
- }
- }
- Log.e(TAG, "Got an empty response");
- return false;
+ public boolean isUsbMassStorageEnabled() {
+ waitForReady();
+ return doGetVolumeShared(Environment.getExternalStorageDirectory().getPath(), "ums");
}
/**
@@ -664,103 +774,38 @@ class MountService extends IMountService.Stub
return mLegacyState;
}
-
- /**
- * Attempt to mount external media
- */
public int mountVolume(String path) {
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- int rc = MountServiceResultCode.OperationSucceeded;
-
- try {
- mConnector.doCommand(String.format("volume mount %s", path));
- } catch (NativeDaemonConnectorException e) {
- /*
- * Mount failed for some reason
- */
- Intent in = null;
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedNoMedia) {
- /*
- * Attempt to mount but no media inserted
- */
- rc = MountServiceResultCode.OperationFailedNoMedia;
- } else if (code == VoldResponseCode.OpFailedMediaBlank) {
- /*
- * Media is blank or does not contain a supported filesystem
- */
- updatePublicVolumeState(path, Environment.MEDIA_NOFS);
- in = new Intent(Intent.ACTION_MEDIA_NOFS, Uri.parse("file://" + path));
- rc = MountServiceResultCode.OperationFailedMediaBlank;
- } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
- /*
- * Volume consistency check failed
- */
- updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
- in = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE, Uri.parse("file://" + path));
- rc = MountServiceResultCode.OperationFailedMediaCorrupt;
- } else {
- rc = MountServiceResultCode.OperationFailedInternalError;
- }
-
- /*
- * Send broadcast intent (if required for the failure)
- */
- if (in != null) {
- mContext.sendBroadcast(in);
- }
- }
-
- return rc;
+ waitForReady();
+ return doMountVolume(path);
}
- /**
- * Attempt to unmount external media to prepare for eject
- */
public int unmountVolume(String path) {
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+ waitForReady();
- try {
- mConnector.doCommand(String.format("volume unmount %s", path));
- return MountServiceResultCode.OperationSucceeded;
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedVolNotMounted) {
- return MountServiceResultCode.OperationFailedVolumeNotMounted;
- } else {
- return MountServiceResultCode.OperationFailedInternalError;
- }
- }
+ return doUnmountVolume(path);
}
- /**
- * Synchronously formats a volume
- *
- * @param path The volume path to format
- * @return Error code from MountServiceResultCode
- */
public int formatVolume(String path) {
validatePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+ waitForReady();
- try {
- String cmd = String.format("volume format %s", path);
- mConnector.doCommand(cmd);
- return MountServiceResultCode.OperationSucceeded;
- } catch (NativeDaemonConnectorException e) {
- int code = e.getCode();
- if (code == VoldResponseCode.OpFailedNoMedia) {
- return MountServiceResultCode.OperationFailedNoMedia;
- } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
- return MountServiceResultCode.OperationFailedMediaCorrupt;
- } else {
- return MountServiceResultCode.OperationFailedInternalError;
- }
+ return doFormatVolume(path);
+ }
+
+ private void warnOnNotMounted() {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ Log.w(TAG, "getSecureContainerList() called when storage not mounted");
}
}
public String[] getSecureContainerList() {
validatePermission(android.Manifest.permission.ASEC_ACCESS);
+ waitForReady();
+ warnOnNotMounted();
+
try {
return mConnector.doListCommand("asec list", VoldResponseCode.AsecListResult);
} catch (NativeDaemonConnectorException e) {
@@ -771,82 +816,124 @@ class MountService extends IMountService.Stub
public int createSecureContainer(String id, int sizeMb, String fstype,
String key, int ownerUid) {
validatePermission(android.Manifest.permission.ASEC_CREATE);
+ waitForReady();
+ warnOnNotMounted();
- int rc = MountServiceResultCode.OperationSucceeded;
+ int rc = StorageResultCode.OperationSucceeded;
String cmd = String.format("asec create %s %d %s %s %d", id, sizeMb, fstype, key, ownerUid);
try {
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
- rc = MountServiceResultCode.OperationFailedInternalError;
+ rc = StorageResultCode.OperationFailedInternalError;
}
return rc;
}
public int finalizeSecureContainer(String id) {
validatePermission(android.Manifest.permission.ASEC_CREATE);
+ warnOnNotMounted();
- int rc = MountServiceResultCode.OperationSucceeded;
+ int rc = StorageResultCode.OperationSucceeded;
try {
mConnector.doCommand(String.format("asec finalize %s", id));
} catch (NativeDaemonConnectorException e) {
- rc = MountServiceResultCode.OperationFailedInternalError;
+ rc = StorageResultCode.OperationFailedInternalError;
}
return rc;
}
public int destroySecureContainer(String id) {
validatePermission(android.Manifest.permission.ASEC_DESTROY);
+ waitForReady();
+ warnOnNotMounted();
- int rc = MountServiceResultCode.OperationSucceeded;
+ int rc = StorageResultCode.OperationSucceeded;
try {
mConnector.doCommand(String.format("asec destroy %s", id));
} catch (NativeDaemonConnectorException e) {
- rc = MountServiceResultCode.OperationFailedInternalError;
+ rc = StorageResultCode.OperationFailedInternalError;
}
return rc;
}
public int mountSecureContainer(String id, String key, int ownerUid) {
validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
+ waitForReady();
+ warnOnNotMounted();
- int rc = MountServiceResultCode.OperationSucceeded;
+ int rc = StorageResultCode.OperationSucceeded;
String cmd = String.format("asec mount %s %s %d", id, key, ownerUid);
try {
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
- rc = MountServiceResultCode.OperationFailedInternalError;
+ rc = StorageResultCode.OperationFailedInternalError;
+ }
+
+ if (rc == StorageResultCode.OperationSucceeded) {
+ synchronized (mAsecMountSet) {
+ mAsecMountSet.add(id);
+ }
}
return rc;
}
public int unmountSecureContainer(String id) {
validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
+ waitForReady();
+ warnOnNotMounted();
+
+ synchronized (mAsecMountSet) {
+ if (!mAsecMountSet.contains(id)) {
+ return StorageResultCode.OperationFailedVolumeNotMounted;
+ }
+ }
- int rc = MountServiceResultCode.OperationSucceeded;
+ int rc = StorageResultCode.OperationSucceeded;
String cmd = String.format("asec unmount %s", id);
try {
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
- rc = MountServiceResultCode.OperationFailedInternalError;
+ rc = StorageResultCode.OperationFailedInternalError;
+ }
+
+ if (rc == StorageResultCode.OperationSucceeded) {
+ synchronized (mAsecMountSet) {
+ mAsecMountSet.remove(id);
+ }
}
return rc;
}
+ public boolean isSecureContainerMounted(String id) {
+ validatePermission(android.Manifest.permission.ASEC_ACCESS);
+ waitForReady();
+ warnOnNotMounted();
+
+ synchronized (mAsecMountSet) {
+ return mAsecMountSet.contains(id);
+ }
+ }
+
public int renameSecureContainer(String oldId, String newId) {
validatePermission(android.Manifest.permission.ASEC_RENAME);
+ waitForReady();
+ warnOnNotMounted();
- int rc = MountServiceResultCode.OperationSucceeded;
+ int rc = StorageResultCode.OperationSucceeded;
String cmd = String.format("asec rename %s %s", oldId, newId);
try {
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
- rc = MountServiceResultCode.OperationFailedInternalError;
+ rc = StorageResultCode.OperationFailedInternalError;
}
return rc;
}
public String getSecureContainerPath(String id) {
validatePermission(android.Manifest.permission.ASEC_ACCESS);
+ waitForReady();
+ warnOnNotMounted();
+
ArrayList<String> rsp = mConnector.doCommand("asec path " + id);
for (String line : rsp) {