summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2011-03-23 14:52:34 -0400
committerMike Lockwood <lockwood@android.com>2011-04-04 18:53:58 -0400
commit7fa24aa8da3d2ab22b3a7d53fe64d14c31c076b8 (patch)
tree351ddbacbe52e21080e951b43b41fff3958b13df /services
parent7f5a026d255fdcbd600a01b4abbd87eb0b528e37 (diff)
downloadframeworks_base-7fa24aa8da3d2ab22b3a7d53fe64d14c31c076b8.zip
frameworks_base-7fa24aa8da3d2ab22b3a7d53fe64d14c31c076b8.tar.gz
frameworks_base-7fa24aa8da3d2ab22b3a7d53fe64d14c31c076b8.tar.bz2
MountService: Add support for multiple volumes
Change-Id: I4eaa781cf302c7aaae170af2489b6b29120c0b81 Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/MountService.java219
1 files changed, 111 insertions, 108 deletions
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 4e80147..59f0852 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -148,7 +148,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
private Context mContext;
private NativeDaemonConnector mConnector;
- private String mLegacyState = Environment.MEDIA_REMOVED;
+ private final HashMap<String, String> mVolumeStates = new HashMap<String, String>();
+ private String mExternalStoragePath;
private PackageManagerService mPms;
private boolean mUmsEnabling;
// Used as a lock for methods that register/unregister listeners.
@@ -453,22 +454,25 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
@Override
public void run() {
try {
- String path = Environment.getExternalStorageDirectory().getPath();
- String state = getVolumeState(path);
-
- if (mEmulateExternalStorage) {
- notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Mounted);
- } else 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));
+ synchronized (mVolumeStates) {
+ for (String path : mVolumeStates.keySet()) {
+ String state = mVolumeStates.get(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)
- */
- notifyVolumeStateChange(null, path, VolumeState.NoMedia, VolumeState.Shared);
}
/*
@@ -519,35 +523,36 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
}
private void updatePublicVolumeState(String path, String state) {
- if (!path.equals(Environment.getExternalStorageDirectory().getPath())) {
- Slog.w(TAG, "Multiple volumes not currently supported");
- return;
+ String oldState;
+ synchronized(mVolumeStates) {
+ oldState = mVolumeStates.put(path, state);
}
-
- if (mLegacyState.equals(state)) {
- Slog.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
+ if (state.equals(oldState)) {
+ Slog.w(TAG, String.format("Duplicate state transition (%s -> %s) for %s",
+ state, state, path));
return;
}
- // Update state on PackageManager, but only of real events
- if (!mEmulateExternalStorage) {
- if (Environment.MEDIA_UNMOUNTED.equals(state)) {
- mPms.updateExternalMediaStatus(false, false);
- /*
- * Some OBBs might have been unmounted when this volume was
- * unmounted, so send a message to the handler to let it know to
- * remove those from the list of mounted OBBS.
- */
- mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_FLUSH_MOUNT_STATE,
- path));
- } else if (Environment.MEDIA_MOUNTED.equals(state)) {
- mPms.updateExternalMediaStatus(true, false);
- }
- }
+ Slog.d(TAG, "volume state changed for " + path + " (" + oldState + " -> " + state + ")");
- String oldState = mLegacyState;
- mLegacyState = state;
+ if (path.equals(mExternalStoragePath)) {
+ // Update state on PackageManager, but only of real events
+ if (!mEmulateExternalStorage) {
+ if (Environment.MEDIA_UNMOUNTED.equals(state)) {
+ mPms.updateExternalMediaStatus(false, false);
+ /*
+ * Some OBBs might have been unmounted when this volume was
+ * unmounted, so send a message to the handler to let it know to
+ * remove those from the list of mounted OBBS.
+ */
+ mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
+ OBB_FLUSH_MOUNT_STATE, path));
+ } else if (Environment.MEDIA_MOUNTED.equals(state)) {
+ mPms.updateExternalMediaStatus(true, false);
+ }
+ }
+ }
synchronized (mListeners) {
for (int i = mListeners.size() -1; i >= 0; i--) {
MountServiceBinderListener bl = mListeners.get(i);
@@ -578,20 +583,15 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
/**
* 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[] tok = volstr.split(" ");
// FMT: <label> <mountpoint> <state>
- if (!tok[1].equals(path)) {
- Slog.w(TAG, String.format(
- "Skipping unknown volume '%s'",tok[1]));
- continue;
- }
+ String path = tok[1];
+ String state = Environment.MEDIA_REMOVED;
+
int st = Integer.parseInt(tok[2]);
if (st == VolumeState.NoMedia) {
state = Environment.MEDIA_REMOVED;
@@ -606,14 +606,15 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
} 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);
+
+ 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);
+ updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED);
}
try {
@@ -1055,11 +1056,12 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
public MountService(Context context) {
mContext = context;
+ mExternalStoragePath = Environment.getExternalStorageDirectory().getPath();
mEmulateExternalStorage = context.getResources().getBoolean(
com.android.internal.R.bool.config_emulateExternalStorage);
if (mEmulateExternalStorage) {
Slog.d(TAG, "using emulated external storage");
- mLegacyState = Environment.MEDIA_MOUNTED;
+ mVolumeStates.put(mExternalStoragePath, Environment.MEDIA_MOUNTED);
}
// XXX: This will go away soon in favor of IMountServiceObserver
@@ -1127,54 +1129,56 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
validatePermission(android.Manifest.permission.SHUTDOWN);
Slog.i(TAG, "Shutting down");
-
- String path = Environment.getExternalStorageDirectory().getPath();
- String state = getVolumeState(path);
-
- if (state.equals(Environment.MEDIA_SHARED)) {
- /*
- * If the media is currently shared, unshare it.
- * XXX: This is still dangerous!. We should not
- * be rebooting at *all* if UMS is enabled, since
- * the UMS host could have dirty FAT cache entries
- * yet to flush.
- */
- setUsbMassStorageEnabled(false);
- } else if (state.equals(Environment.MEDIA_CHECKING)) {
- /*
- * If the media is being checked, then we need to wait for
- * it to complete before being able to proceed.
- */
- // XXX: @hackbod - Should we disable the ANR timer here?
- int retries = 30;
- while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException iex) {
- Slog.e(TAG, "Interrupted while waiting for media", iex);
- break;
+ synchronized (mVolumeStates) {
+ for (String path : mVolumeStates.keySet()) {
+ String state = mVolumeStates.get(path);
+
+ if (state.equals(Environment.MEDIA_SHARED)) {
+ /*
+ * If the media is currently shared, unshare it.
+ * XXX: This is still dangerous!. We should not
+ * be rebooting at *all* if UMS is enabled, since
+ * the UMS host could have dirty FAT cache entries
+ * yet to flush.
+ */
+ setUsbMassStorageEnabled(false);
+ } else if (state.equals(Environment.MEDIA_CHECKING)) {
+ /*
+ * If the media is being checked, then we need to wait for
+ * it to complete before being able to proceed.
+ */
+ // XXX: @hackbod - Should we disable the ANR timer here?
+ int retries = 30;
+ while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException iex) {
+ Slog.e(TAG, "Interrupted while waiting for media", iex);
+ break;
+ }
+ state = Environment.getExternalStorageState();
+ }
+ if (retries == 0) {
+ Slog.e(TAG, "Timed out waiting for media to check");
+ }
}
- state = Environment.getExternalStorageState();
- }
- if (retries == 0) {
- Slog.e(TAG, "Timed out waiting for media to check");
- }
- }
- if (state.equals(Environment.MEDIA_MOUNTED)) {
- // Post a unmount message.
- ShutdownCallBack ucb = new ShutdownCallBack(path, observer);
- mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
- } else if (observer != null) {
- /*
- * Observer is waiting for onShutDownComplete when we are done.
- * Since nothing will be done send notification directly so shutdown
- * sequence can continue.
- */
- try {
- observer.onShutDownComplete(StorageResultCode.OperationSucceeded);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException when shutting down");
+ if (state.equals(Environment.MEDIA_MOUNTED)) {
+ // Post a unmount message.
+ ShutdownCallBack ucb = new ShutdownCallBack(path, observer);
+ mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
+ } else if (observer != null) {
+ /*
+ * Observer is waiting for onShutDownComplete when we are done.
+ * Since nothing will be done send notification directly so shutdown
+ * sequence can continue.
+ */
+ try {
+ observer.onShutDownComplete(StorageResultCode.OperationSucceeded);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException when shutting down");
+ }
+ }
}
}
}
@@ -1246,16 +1250,15 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
* @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();
- }
+ synchronized (mVolumeStates) {
+ String state = mVolumeStates.get(mountPoint);
+ if (state == null) {
+ Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
+ throw new IllegalArgumentException();
+ }
- return mLegacyState;
+ return state;
+ }
}
public boolean isExternalStorageEmulated() {