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-05-03 21:03:55 -0400
commitf097fc2fee57183508558acbca1f8742fb55615a (patch)
tree563a1d88fc67e15216aaa4f93611fcd4b8f349e9 /services
parent7c2d14d59637cfb06ebcfbb091541cebd131fc6a (diff)
downloadframeworks_base-f097fc2fee57183508558acbca1f8742fb55615a.zip
frameworks_base-f097fc2fee57183508558acbca1f8742fb55615a.tar.gz
frameworks_base-f097fc2fee57183508558acbca1f8742fb55615a.tar.bz2
DO NOT MERGE MountService: Add support for multiple volumes
Change-Id: I45ee0e5735a6d72c635f6d22320e8b13bccc3847 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 91ada6b..461a21e 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -144,7 +144,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.
@@ -449,22 +450,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);
}
/*
@@ -516,35 +520,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);
@@ -575,20 +580,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;
@@ -603,14 +603,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 {
@@ -1052,11 +1053,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
@@ -1125,54 +1127,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");
+ }
+ }
}
}
}
@@ -1244,16 +1248,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() {