summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoushik Dutta <koushd@gmail.com>2010-08-27 15:51:24 -0700
committerKoushik Dutta <koushd@gmail.com>2010-08-27 15:51:24 -0700
commit93bb95929a0c017498625a87654b4d114fe17b96 (patch)
treeecdbfe15e1f59f0760612d11189c7bebbf8ed5e8
parent5722ad7ba282fd3dff28fc700d6556a4bd1ff52a (diff)
downloadframeworks_base-93bb95929a0c017498625a87654b4d114fe17b96.zip
frameworks_base-93bb95929a0c017498625a87654b4d114fe17b96.tar.gz
frameworks_base-93bb95929a0c017498625a87654b4d114fe17b96.tar.bz2
Add support for mounting and sharing of multiple volumes to MountService.
-rw-r--r--services/java/com/android/server/MountService.java192
1 files changed, 104 insertions, 88 deletions
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index cb55808..e147b68 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -40,6 +40,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Slog;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
/**
@@ -114,7 +115,7 @@ class MountService extends IMountService.Stub
private Context mContext;
private NativeDaemonConnector mConnector;
- private String mLegacyState = Environment.MEDIA_REMOVED;
+ HashMap<String, String> mVolumeStates = new HashMap<String, String>();
private PackageManagerService mPms;
private boolean mUmsEnabling;
// Used as a lock for methods that register/unregister listeners.
@@ -305,33 +306,36 @@ class MountService extends IMountService.Stub
}
new Thread() {
public void run() {
- try {
- String path = Environment.getExternalStorageDirectory().getPath();
- String state = getVolumeState(path);
-
- if (state.equals(Environment.MEDIA_UNMOUNTED)) {
- int rc = doMountVolume(path);
- if (rc != StorageResultCode.OperationSucceeded) {
- Slog.e(TAG, String.format("Boot-time mount failed (%d)", rc));
+ ArrayList<String> volumesToMount = getShareableVolumes();
+
+ for (String path: volumesToMount) {
+ try {
+ String state = getVolumeState(path);
+
+ if (state.equals(Environment.MEDIA_UNMOUNTED)) {
+ int rc = doMountVolume(path);
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Slog.e(TAG, String.format("Boot-time mount failed (%d)", rc));
+ }
+ } else if (state.equals(Environment.MEDIA_SHARED)) {
+ /*
+ * Bootstrap UMS enabled state since vold indicates
+ * the volume is shared (runtime restart while ums enabled)
+ */
+ notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Shared);
}
- } else if (state.equals(Environment.MEDIA_SHARED)) {
+
/*
- * Bootstrap UMS enabled state since vold indicates
- * the volume is shared (runtime restart while ums enabled)
+ * If UMS was connected on boot, send the connected event
+ * now that we're up.
*/
- notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Shared);
- }
-
- /*
- * If UMS was connected on boot, send the connected event
- * now that we're up.
- */
- if (mSendUmsConnectedOnBoot) {
- sendUmsIntent(true);
- mSendUmsConnectedOnBoot = false;
+ if (mSendUmsConnectedOnBoot) {
+ sendUmsIntent(true);
+ mSendUmsConnectedOnBoot = false;
+ }
+ } catch (Exception ex) {
+ Slog.e(TAG, "Boot-time mount exception", ex);
}
- } catch (Exception ex) {
- Slog.e(TAG, "Boot-time mount exception", ex);
}
}
}.start();
@@ -371,13 +375,9 @@ class MountService extends IMountService.Stub
}
private void updatePublicVolumeState(String path, String state) {
- if (!path.equals(Environment.getExternalStorageDirectory().getPath())) {
- Slog.w(TAG, "Multiple volumes not currently supported");
- return;
- }
-
- if (mLegacyState.equals(state)) {
- Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
+ String currentState = getVolumeState(path);
+ if (currentState.equals(state)) {
+ Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", currentState, state));
return;
}
// Update state on PackageManager
@@ -386,8 +386,8 @@ class MountService extends IMountService.Stub
} else if (Environment.MEDIA_MOUNTED.equals(state)) {
mPms.updateExternalMediaStatus(true, false);
}
- String oldState = mLegacyState;
- mLegacyState = state;
+ String oldState = currentState;
+ setVolumeState(path, state);
synchronized (mListeners) {
for (int i = mListeners.size() -1; i >= 0; i--) {
@@ -418,20 +418,15 @@ class MountService extends IMountService.Stub
/**
* Determine media state and UMS detection status
*/
- String path = Environment.getExternalStorageDirectory().getPath();
- String state = Environment.MEDIA_REMOVED;
-
- try {
- String[] vols = mConnector.doListCommand(
- "volume list", VoldResponseCode.VolumeListResult);
- for (String volstr : vols) {
+ String[] vols = mConnector.doListCommand(
+ "volume list", VoldResponseCode.VolumeListResult);
+ for (String volstr : vols) {
+ String path = null;
+ String state = Environment.MEDIA_REMOVED;
+ try {
String[] tok = volstr.split(" ");
+ path = tok[1];
// FMT: <label> <mountpoint> <state>
- if (!tok[1].equals(path)) {
- Slog.w(TAG, String.format(
- "Skipping unknown volume '%s'",tok[1]));
- continue;
- }
int st = Integer.parseInt(tok[2]);
if (st == VolumeState.NoMedia) {
state = Environment.MEDIA_REMOVED;
@@ -446,14 +441,14 @@ class MountService extends IMountService.Stub
} else {
throw new Exception(String.format("Unexpected state %d", st));
}
+ if (state != null) {
+ if (DEBUG_EVENTS) Slog.i(TAG, "Updating valid state " + state);
+ updatePublicVolumeState(path, state);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error processing initial volume state", e);
+ if (path != null) updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
}
- if (state != null) {
- if (DEBUG_EVENTS) Slog.i(TAG, "Updating valid state " + state);
- updatePublicVolumeState(path, state);
- }
- } catch (Exception e) {
- Slog.e(TAG, "Error processing initial volume state", e);
- updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
}
try {
@@ -580,6 +575,7 @@ class MountService extends IMountService.Stub
private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
String vs = getVolumeState(path);
if (DEBUG_EVENTS) Slog.i(TAG, "notifyVolumeStateChanged::" + vs);
+ Slog.i(TAG, String.format("notifyVolumeStateChange %s %s %s %s", label, path, oldState, newState));
Intent in = null;
@@ -981,40 +977,59 @@ class MountService extends IMountService.Stub
}
return doGetShareMethodAvailable("ums");
}
+
+ private ArrayList<String> getShareableVolumes() {
+ // build.prop will specify additional volumes to mount in the
+ // ro.additionalmounts property.
+ // This is a semicolon delimited list of paths. Such as "/emmc;/foo", etc.
+ ArrayList<String> volumesToMount = new ArrayList<String>();
+ volumesToMount.add(Environment.getExternalStorageDirectory().getPath());
+ String additionalVolumesProperty = SystemProperties.get("ro.additionalmounts");
+ if (null != additionalVolumesProperty) {
+ String[] additionalVolumes = additionalVolumesProperty.split(";");
+ for (String additionalVolume: additionalVolumes) {
+ if (!"".equals(additionalVolume)) {
+ volumesToMount.add(additionalVolume);
+ }
+ }
+ }
+ return volumesToMount;
+ }
public void setUsbMassStorageEnabled(boolean enable) {
waitForReady();
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- // TODO: Add support for multiple share methods
+ ArrayList<String> volumesToShare = getShareableVolumes();
- /*
- * If the volume is mounted and we're enabling then unmount it
- */
- String path = Environment.getExternalStorageDirectory().getPath();
- String vs = getVolumeState(path);
- String method = "ums";
- if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
- // Override for isUsbMassStorageEnabled()
- setUmsEnabling(enable);
- UmsEnableCallBack umscb = new UmsEnableCallBack(path, method, true);
- mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, umscb));
- // Clear override
- setUmsEnabling(false);
- }
- /*
- * If we disabled UMS then mount the volume
- */
- if (!enable) {
- doShareUnshareVolume(path, method, enable);
- if (doMountVolume(path) != StorageResultCode.OperationSucceeded) {
- Slog.e(TAG, "Failed to remount " + path +
- " after disabling share method " + method);
- /*
- * Even though the mount failed, the unshare didn't so don't indicate an error.
- * The mountVolume() call will have set the storage state and sent the necessary
- * broadcasts.
- */
+ for (String path: volumesToShare) {
+ /*
+ * If the volume is mounted and we're enabling then unmount it
+ */
+ String vs = getVolumeState(path);
+ String method = "ums";
+ if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
+ // Override for isUsbMassStorageEnabled()
+ setUmsEnabling(enable);
+ UmsEnableCallBack umscb = new UmsEnableCallBack(path, method, true);
+ mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, umscb));
+ // Clear override
+ setUmsEnabling(false);
+ }
+ /*
+ * If we disabled UMS then mount the volume
+ */
+ if (!enable) {
+ doShareUnshareVolume(path, method, enable);
+ if (doMountVolume(path) != StorageResultCode.OperationSucceeded) {
+ Slog.e(TAG, "Failed to remount " + path +
+ " after disabling share method " + method);
+ /*
+ * Even though the mount failed, the unshare didn't so don't indicate an error.
+ * The mountVolume() call will have set the storage state and sent the necessary
+ * broadcasts.
+ */
+ }
}
}
}
@@ -1028,16 +1043,17 @@ class MountService extends IMountService.Stub
* @return state of the volume at the specified mount point
*/
public String getVolumeState(String mountPoint) {
- /*
- * XXX: Until we have multiple volume discovery, just hardwire
- * this to /sdcard
- */
- if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
- Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
- throw new IllegalArgumentException();
+ String volumeState = mVolumeStates.get(mountPoint);
+ if (null == volumeState) {
+ setVolumeState(mountPoint, Environment.MEDIA_REMOVED);
+ return Environment.MEDIA_REMOVED;
}
- return mLegacyState;
+ return volumeState;
+ }
+
+ private void setVolumeState(String mountPoint, String volumeState) {
+ mVolumeStates.put(mountPoint, volumeState);
}
public int mountVolume(String path) {