summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2010-02-05 08:26:50 -0800
committerSan Mehat <san@google.com>2010-02-09 11:03:16 -0800
commitb104340496e3a531e26c8f428c808eca0e039f50 (patch)
tree11247cb68359d43ca4871c0cb0165c9bec339a6f /core
parent3ee1317173260252d475772fec09d492f8fcfd33 (diff)
downloadframeworks_base-b104340496e3a531e26c8f428c808eca0e039f50.zip
frameworks_base-b104340496e3a531e26c8f428c808eca0e039f50.tar.gz
frameworks_base-b104340496e3a531e26c8f428c808eca0e039f50.tar.bz2
Framework: Clean up / Refactor Mount APIs
- Move android.storage.* -> android.os.storage.* and refactor users - Refactor generic shares back to explicit ums enable/disable/isEnabled - Remove media insert/removed event callbacks (not ready for Froyo) - Remove 'label' from volume state change callbacks - Add public API functions for enabling/disabling USB mass storage (permissions enforced in MountSevice) - Remove some stray un-needed import lines - Move android.os.IMountService / android.os.IMountServiceListener -> android.os.storage - Improve code comments Updated: MountService: Add dup state check and move debugging behind a conditional UsbStorageActivity: Fix review comments + a TODO StorageNotification: Add @Override tags StorageManager: Don't use a static Listener list MountService: Reduce bloat and fix == where I meant .equals() PackageManagerTests: Update for new API Signed-off-by: San Mehat <san@google.com>
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/ContextImpl.java2
-rw-r--r--core/java/android/content/Context.java6
-rw-r--r--core/java/android/os/Environment.java2
-rw-r--r--core/java/android/os/IMountServiceListener.aidl66
-rw-r--r--core/java/android/os/MountServiceListener.java69
-rw-r--r--core/java/android/os/Power.java2
-rw-r--r--core/java/android/os/storage/IMountService.aidl (renamed from core/java/android/os/IMountService.aidl)31
-rw-r--r--core/java/android/os/storage/IMountServiceListener.aidl43
-rw-r--r--core/java/android/os/storage/MountServiceListener.java44
-rw-r--r--core/java/android/os/storage/StorageEventListener.java38
-rw-r--r--core/java/android/os/storage/StorageManager.java297
-rw-r--r--core/java/android/os/storage/StorageResultCode.java (renamed from core/java/android/os/MountServiceResultCode.java)40
-rw-r--r--core/java/android/storage/StorageEventListener.java57
-rw-r--r--core/java/android/storage/StorageManager.java304
-rw-r--r--core/java/com/android/internal/app/ExternalMediaFormatActivity.java2
-rwxr-xr-xcore/java/com/android/internal/app/NetInitiatedActivity.java1
-rw-r--r--core/java/com/android/internal/app/ShutdownThread.java2
-rw-r--r--core/java/com/android/internal/app/StorageNotification.java175
-rw-r--r--core/java/com/android/internal/app/TetherActivity.java1
-rw-r--r--core/java/com/android/internal/app/UsbStorageActivity.java93
20 files changed, 621 insertions, 654 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 45d7546..4923eee 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -84,7 +84,7 @@ import android.os.ServiceManager;
import android.os.StatFs;
import android.os.Vibrator;
import android.os.FileUtils.FileStatus;
-import android.storage.StorageManager;
+import android.os.storage.StorageManager;
import android.telephony.TelephonyManager;
import android.text.ClipboardManager;
import android.util.AndroidRuntimeException;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5aefe4c..b4a0bf8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1110,7 +1110,7 @@ public abstract class Context {
* @see #SENSOR_SERVICE
* @see android.hardware.SensorManager
* @see #STORAGE_SERVICE
- * @see android.storage.StorageManager
+ * @see android.os.storage.StorageManager
* @see #VIBRATOR_SERVICE
* @see android.os.Vibrator
* @see #CONNECTIVITY_SERVICE
@@ -1243,11 +1243,11 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.storage.StorageManager} for accesssing system storage
+ * android.os.storage.StorageManager} for accesssing system storage
* functions.
*
* @see #getSystemService
- * @see android.storage.StorageManager
+ * @see android.os.storage.StorageManager
*/
public static final String STORAGE_SERVICE = "storage";
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 9491bd4..ef1f3be 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -18,7 +18,7 @@ package android.os;
import java.io.File;
-import android.os.IMountService;
+import android.os.storage.IMountService;
/**
* Provides access to environment variables.
diff --git a/core/java/android/os/IMountServiceListener.aidl b/core/java/android/os/IMountServiceListener.aidl
deleted file mode 100644
index 3df64b2..0000000
--- a/core/java/android/os/IMountServiceListener.aidl
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Callback class for receiving events from MountService.
- *
- * @hide
- */
-interface IMountServiceListener {
- /**
- * A sharing method has changed availability state.
- *
- * @param method The share method which has changed.
- * @param available The share availability state.
- */
- void onShareAvailabilityChanged(String method, boolean available);
-
- /**
- * Media has been inserted
- *
- * @param label The volume label.
- * @param path The volume mount path.
- * @param major The backing device major number.
- * @param minor The backing device minor number.
- */
- void onMediaInserted(String label, String path, int major, int minor);
-
- /**
- * Media has been removed
- *
- * @param label The volume label.
- * @param path The volume mount path.
- * @param major The backing device major number.
- * @param minor The backing device minor number.
- * @param clean Indicates if the removal was clean (unmounted first).
- */
- void onMediaRemoved(String label, String path, int major, int minor, boolean clean);
-
- /**
- * Volume state has changed.
- *
- * @param label The volume label.
- * @param path The volume mount path.
- * @param oldState The old state of the volume.
- * @param newState The new state of the volume.
- *
- * Note: State is one of the values returned by Environment.getExternalStorageState()
- */
- void onVolumeStateChanged(String label, String path, String oldState, String newState);
-
-}
diff --git a/core/java/android/os/MountServiceListener.java b/core/java/android/os/MountServiceListener.java
deleted file mode 100644
index a68f464..0000000
--- a/core/java/android/os/MountServiceListener.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Callback class for receiving progress reports during a restore operation. These
- * methods will all be called on your application's main thread.
- * @hide
- */
-public abstract class MountServiceListener {
- /**
- * A sharing method has changed availability state.
- *
- * @param method The share method which has changed.
- * @param available The share availability state.
- */
- void shareAvailabilityChange(String method, boolean available) {
- }
-
- /**
- * Media has been inserted
- *
- * @param label The volume label.
- * @param path The volume mount path.
- * @param major The backing device major number.
- * @param minor The backing device minor number.
- */
- void mediaInserted(String label, String path, int major, int minor) {
- }
-
- /**
- * Media has been removed
- *
- * @param label The volume label.
- * @param path The volume mount path.
- * @param major The backing device major number.
- * @param minor The backing device minor number.
- * @param clean Indicates if the removal was clean (unmounted first).
- */
- void mediaRemoved(String label, String path, int major, int minor, boolean clean) {
- }
-
- /**
- * Volume state has changed.
- *
- * @param label The volume label.
- * @param path The volume mount path.
- * @param oldState The old state of the volume.
- * @param newState The new state of the volume.
- *
- * Note: State is one of the values returned by Environment.getExternalStorageState()
- */
- void volumeStateChange(String label, String path, String oldState, String newState) {
- }
-}
diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java
index bc76180..b3df522 100644
--- a/core/java/android/os/Power.java
+++ b/core/java/android/os/Power.java
@@ -18,7 +18,7 @@ package android.os;
import java.io.IOException;
import android.os.ServiceManager;
-import android.os.IMountService;
+import android.os.storage.IMountService;
/**
* Class that provides access to some of the power management functions.
diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
index a5828f6..84e3f58 100644
--- a/core/java/android/os/IMountService.aidl
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -15,14 +15,15 @@
** limitations under the License.
*/
-package android.os;
+package android.os.storage;
-import android.os.IMountServiceListener;
+import android.os.storage.IMountServiceListener;
/** WARNING! Update IMountService.h and IMountService.cpp if you change this file.
* In particular, the ordering of the methods below must match the
* _TRANSACTION enum in IMountService.cpp
- * @hide
+ * @hide - Applications should use android.os.storage.StorageManager to access
+ * storage functions.
*/
interface IMountService
{
@@ -38,31 +39,19 @@ interface IMountService
void unregisterListener(IMountServiceListener listener);
/**
- * Gets an Array of supported share methods
+ * Returns true if a USB mass storage host is connected
*/
- String[] getShareMethodList();
+ boolean isUsbMassStorageConnected();
/**
- * Returns true if the share method is available
+ * Enables / disables USB mass storage.
*/
- boolean getShareMethodAvailable(String method);
+ int setUsbMassStorageEnabled(boolean enable);
/**
- * Shares a volume via the specified method
- * Returns an int consistent with MountServiceResultCode
- */
- int shareVolume(String path, String method);
-
- /**
- * Unshares a volume via the specified method
- * Returns an int consistent with MountServiceResultCode
- */
- int unshareVolume(String path, String method);
-
- /**
- * Returns true if the volume is shared via the specified method.
+ * Returns true if a USB mass storage host is enabled (media is shared)
*/
- boolean getVolumeShared(String path, String method);
+ boolean isUsbMassStorageEnabled();
/**
* Mount external storage at given mount point.
diff --git a/core/java/android/os/storage/IMountServiceListener.aidl b/core/java/android/os/storage/IMountServiceListener.aidl
new file mode 100644
index 0000000..883413a
--- /dev/null
+++ b/core/java/android/os/storage/IMountServiceListener.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Callback class for receiving events from MountService.
+ *
+ * @hide - Applications should use android.os.storage.IStorageEventListener
+ * for storage event callbacks.
+ */
+interface IMountServiceListener {
+ /**
+ * Detection state of USB Mass Storage has changed
+ *
+ * @param available true if a UMS host is connected.
+ */
+ void onUsbMassStorageConnectionChanged(boolean connected);
+
+ /**
+ * Storage state has changed.
+ *
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume.
+ *
+ * Note: State is one of the values returned by Environment.getExternalStorageState()
+ */
+ void onStorageStateChanged(String path, String oldState, String newState);
+}
diff --git a/core/java/android/os/storage/MountServiceListener.java b/core/java/android/os/storage/MountServiceListener.java
new file mode 100644
index 0000000..bebb3f6
--- /dev/null
+++ b/core/java/android/os/storage/MountServiceListener.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Callback class for receiving progress reports during a restore operation. These
+ * methods will all be called on your application's main thread.
+ * @hide
+ */
+public abstract class MountServiceListener {
+ /**
+ * USB Mass storage connection state has changed.
+ *
+ * @param connected True if UMS is connected.
+ */
+ void onUsbMassStorageConnectionChanged(boolean connected) {
+ }
+
+ /**
+ * Storage state has changed.
+ *
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume.
+ *
+ * @Note: State is one of the values returned by Environment.getExternalStorageState()
+ */
+ void onStorageStateChange(String path, String oldState, String newState) {
+ }
+}
diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java
new file mode 100644
index 0000000..d3d39d6
--- /dev/null
+++ b/core/java/android/os/storage/StorageEventListener.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Used for receiving notifications from the StorageManager
+ */
+public abstract class StorageEventListener {
+ /**
+ * Called when the detection state of a USB Mass Storage host has changed.
+ * @param connected true if the USB mass storage is connected.
+ */
+ public void onUsbMassStorageConnectionChanged(boolean connected) {
+ }
+
+ /**
+ * Called when storage has changed state
+ * @param path the filesystem path for the storage
+ * @param oldState the old state as returned by {@link android.os.Environment#getExternalStorageState()}.
+ * @param newState the old state as returned by {@link android.os.Environment#getExternalStorageState()}.
+ */
+ public void onStorageStateChanged(String path, String oldState, String newState) {
+ }
+}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
new file mode 100644
index 0000000..e421ea5
--- /dev/null
+++ b/core/java/android/os/storage/StorageManager.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.Parcelable;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.os.storage.IMountService;
+import android.os.storage.IMountServiceListener;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * StorageManager is the interface to the systems storage service.
+ * Get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
+ * of {@link android.content.Context#STORAGE_SERVICE}.
+ *
+ */
+
+public class StorageManager
+{
+ private static final String TAG = "StorageManager";
+
+ /*
+ * Our internal MountService binder reference
+ */
+ private IMountService mMountService;
+
+ /*
+ * The looper target for callbacks
+ */
+ Looper mTgtLooper;
+
+ /*
+ * Target listener for binder callbacks
+ */
+ private MountServiceBinderListener mBinderListener;
+
+ /*
+ * List of our listeners
+ */
+ private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
+
+ private class MountServiceBinderListener extends IMountServiceListener.Stub {
+ public void onUsbMassStorageConnectionChanged(boolean available) {
+ final int size = mListeners.size();
+ for (int i = 0; i < size; i++) {
+ mListeners.get(i).sendShareAvailabilityChanged(available);
+ }
+ }
+
+ public void onStorageStateChanged(String path, String oldState, String newState) {
+ final int size = mListeners.size();
+ for (int i = 0; i < size; i++) {
+ mListeners.get(i).sendStorageStateChanged(path, oldState, newState);
+ }
+ }
+ }
+
+ /**
+ * Private base class for messages sent between the callback thread
+ * and the target looper handler.
+ */
+ private class StorageEvent {
+ public static final int EVENT_UMS_CONNECTION_CHANGED = 1;
+ public static final int EVENT_STORAGE_STATE_CHANGED = 2;
+
+ private Message mMessage;
+
+ public StorageEvent(int what) {
+ mMessage = Message.obtain();
+ mMessage.what = what;
+ mMessage.obj = this;
+ }
+
+ public Message getMessage() {
+ return mMessage;
+ }
+ }
+
+ /**
+ * Message sent on a USB mass storage connection change.
+ */
+ private class UmsConnectionChangedStorageEvent extends StorageEvent {
+ public boolean available;
+
+ public UmsConnectionChangedStorageEvent(boolean a) {
+ super(EVENT_UMS_CONNECTION_CHANGED);
+ available = a;
+ }
+ }
+
+ /**
+ * Message sent on volume state change.
+ */
+ private class StorageStateChangedStorageEvent extends StorageEvent {
+ public String path;
+ public String oldState;
+ public String newState;
+
+ public StorageStateChangedStorageEvent(String p, String oldS, String newS) {
+ super(EVENT_STORAGE_STATE_CHANGED);
+ path = p;
+ oldState = oldS;
+ newState = newS;
+ }
+ }
+
+ /**
+ * Private class containing sender and receiver code for StorageEvents.
+ */
+ private class ListenerDelegate {
+ final StorageEventListener mStorageEventListener;
+ private final Handler mHandler;
+
+ ListenerDelegate(StorageEventListener listener) {
+ mStorageEventListener = listener;
+ mHandler = new Handler(mTgtLooper) {
+ @Override
+ public void handleMessage(Message msg) {
+ StorageEvent e = (StorageEvent) msg.obj;
+
+ if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {
+ UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e;
+ mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
+ } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) {
+ StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e;
+ mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState);
+ } else {
+ Log.e(TAG, "Unsupported event " + msg.what);
+ }
+ }
+ };
+ }
+
+ StorageEventListener getListener() {
+ return mStorageEventListener;
+ }
+
+ void sendShareAvailabilityChanged(boolean available) {
+ UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available);
+ mHandler.sendMessage(e.getMessage());
+ }
+
+ void sendStorageStateChanged(String path, String oldState, String newState) {
+ StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState);
+ mHandler.sendMessage(e.getMessage());
+ }
+ }
+
+ /**
+ * Constructs a StorageManager object through which an application can
+ * can communicate with the systems mount service.
+ *
+ * @param tgtLooper The {@android.os.Looper} which events will be received on.
+ *
+ * <p>Applications can get instance of this class by calling
+ * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
+ * of {@link android.content.Context#STORAGE_SERVICE}.
+ *
+ * @hide
+ */
+ public StorageManager(Looper tgtLooper) throws RemoteException {
+ mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
+ if (mMountService == null) {
+ Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
+ return;
+ }
+ mTgtLooper = tgtLooper;
+ mBinderListener = new MountServiceBinderListener();
+ mMountService.registerListener(mBinderListener);
+ }
+
+
+ /**
+ * Registers a {@link android.os.storage.StorageEventListener StorageEventListener}.
+ *
+ * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
+ *
+ */
+ public void registerListener(StorageEventListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ synchronized (mListeners) {
+ mListeners.add(new ListenerDelegate(listener));
+ }
+ }
+
+ /**
+ * Unregisters a {@link android.os.storage.StorageEventListener StorageEventListener}.
+ *
+ * @param listener A {@link android.os.storage.StorageEventListener StorageEventListener} object.
+ *
+ */
+ public void unregisterListener(StorageEventListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ synchronized (mListeners) {
+ final int size = mListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ ListenerDelegate l = mListeners.get(i);
+ if (l.getListener() == listener) {
+ mListeners.remove(i);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Enables USB Mass Storage (UMS) on the device.
+ * @return an integer value representing the outcome of the operation.
+ * @see android.os.storage.StorageResultCode
+ */
+ public int enableUsbMassStorage() {
+ try {
+ return mMountService.setUsbMassStorageEnabled(true);
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed to enable UMS", ex);
+ }
+ return StorageResultCode.OperationFailedInternalError;
+ }
+
+ /**
+ * Disables USB Mass Storage (UMS) on the device.
+ * @return an integer value representing the outcome of the operation.
+ * @see android.os.storage.StorageResultCode
+ */
+ public int disableUsbMassStorage() {
+ try {
+ return mMountService.setUsbMassStorageEnabled(false);
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed to disable UMS", ex);
+ }
+ return StorageResultCode.OperationFailedInternalError;
+ }
+
+ /**
+ * Query if a USB Mass Storage (UMS) host is connected.
+ * @return true if UMS host is connected.
+ */
+ public boolean isUsbMassStorageConnected() {
+ try {
+ return mMountService.isUsbMassStorageConnected();
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed to get UMS connection state", ex);
+ }
+ return false;
+ }
+
+ /**
+ * Query if a USB Mass Storage (UMS) is enabled on the device.
+ * @return true if UMS host is enabled.
+ */
+ public boolean isUsbMassStorageEnabled() {
+ try {
+ return mMountService.isUsbMassStorageEnabled();
+ } catch (RemoteException rex) {
+ Log.e(TAG, "Failed to get UMS enable state", rex);
+ }
+ return false;
+ }
+}
diff --git a/core/java/android/os/MountServiceResultCode.java b/core/java/android/os/storage/StorageResultCode.java
index e71dbf4..584f160 100644
--- a/core/java/android/os/MountServiceResultCode.java
+++ b/core/java/android/os/storage/StorageResultCode.java
@@ -14,21 +14,47 @@
* limitations under the License.
*/
-package android.os;
-
-import java.io.IOException;
+package android.os.storage;
/**
- * Class that provides access to constants returned from MountService APIs
- *
- * {@hide}
+ * Class that provides access to constants returned from StorageManager
+ * and lower level MountService APIs.
*/
-public class MountServiceResultCode
+public class StorageResultCode
{
+ /**
+ * Operation succeeded.
+ * @see android.os.storage.StorageManager
+ */
public static final int OperationSucceeded = 0;
+
+ /**
+ * Operation failed: Internal error.
+ * @see android.os.storage.StorageManager
+ */
public static final int OperationFailedInternalError = -1;
+
+ /**
+ * Operation failed: Missing media.
+ * @see android.os.storage.StorageManager
+ */
public static final int OperationFailedNoMedia = -2;
+
+ /**
+ * Operation failed: Media is blank.
+ * @see android.os.storage.StorageManager
+ */
public static final int OperationFailedMediaBlank = -3;
+
+ /**
+ * Operation failed: Media is corrupt.
+ * @see android.os.storage.StorageManager
+ */
public static final int OperationFailedMediaCorrupt = -4;
+
+ /**
+ * Operation failed: Media not mounted.
+ * @see android.os.storage.StorageManager
+ */
public static final int OperationFailedVolumeNotMounted = -5;
}
diff --git a/core/java/android/storage/StorageEventListener.java b/core/java/android/storage/StorageEventListener.java
deleted file mode 100644
index cd71090..0000000
--- a/core/java/android/storage/StorageEventListener.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.storage;
-
-/**
- * Used for receiving notifications from the StorageManager
- */
-public interface StorageEventListener {
- /**
- * Called when the ability to share a volume has changed.
- * @param method the share-method which has changed.
- * @param available true if the share is available.
- */
- public void onShareAvailabilityChanged(String method, boolean available);
-
- /**
- * Called when media has been inserted
- * @param label the system defined label for the volume.
- * @param path the filesystem path for the volume.
- * @param major the major number of the device.
- * @param minor the minor number of the device.
- */
- public void onMediaInserted(String label, String path, int major, int minor);
-
- /**
- * Called when media has been removed
- * @param label the system defined label for the volume.
- * @param path the filesystem path for the volume.
- * @param major the major number of the device.
- * @param minor the minor number of the device.
- * @param clean the media was removed cleanly.
- */
- public void onMediaRemoved(String label, String path, int major, int minor, boolean clean);
-
- /**
- * Called when a volume has changed state
- * @param label the system defined label for the volume.
- * @param path the filesystem path for the volume.
- * @param oldState the old state as returned by {@link android.os.Environment#getExternalStorageState()}.
- * @param newState the old state as returned by {@link android.os.Environment#getExternalStorageState()}.
- */
- public void onVolumeStateChanged(String label, String path, String oldState, String newState);
-}
diff --git a/core/java/android/storage/StorageManager.java b/core/java/android/storage/StorageManager.java
deleted file mode 100644
index 924d169..0000000
--- a/core/java/android/storage/StorageManager.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.storage;
-
-import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ServiceManager;
-import android.os.IMountService;
-import android.os.IMountServiceListener;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Class that lets you access the device's storage management functions. Get an instance of this
- * class by calling {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with an argument of {@link android.content.Context#STORAGE_SERVICE}.
- */
-public class StorageManager
-{
- private static final String TAG = "StorageManager";
-
- /*
- * Our internal MountService binder reference
- */
- private IMountService mMountService;
-
- /*
- * The looper target for callbacks
- */
- Looper mTgtLooper;
-
- /*
- * Target listener for binder callbacks
- */
- private MountServiceBinderListener mBinderListener;
-
- /*
- * *static* list of our listeners
- */
- static final ArrayList<ListenerDelegate> sListeners = new ArrayList<ListenerDelegate>();
-
- private class MountServiceBinderListener extends IMountServiceListener.Stub {
- public void onShareAvailabilityChanged(String method, boolean available) {
- final int size = sListeners.size();
- for (int i = 0; i < size; i++) {
- sListeners.get(i).sendShareAvailabilityChanged(method, available);
- }
- }
-
- public void onMediaInserted(String label, String path, int major, int minor) {
- final int size = sListeners.size();
- for (int i = 0; i < size; i++) {
- sListeners.get(i).sendMediaInserted(label, path, major, minor);
- }
- }
-
- public void onMediaRemoved(String label, String path, int major, int minor, boolean clean) {
- final int size = sListeners.size();
- for (int i = 0; i < size; i++) {
- sListeners.get(i).sendMediaRemoved(label, path, major, minor, clean);
- }
- }
-
- public void onVolumeStateChanged(String label, String path, String oldState, String newState) {
- final int size = sListeners.size();
- for (int i = 0; i < size; i++) {
- sListeners.get(i).sendVolumeStateChanged(label, path, oldState, newState);
- }
- }
- }
-
- /**
- * Private base class for messages sent between the callback thread
- * and the target looper handler
- */
- private class StorageEvent {
- public static final int EVENT_SHARE_AVAILABILITY_CHANGED = 1;
- public static final int EVENT_MEDIA_INSERTED = 2;
- public static final int EVENT_MEDIA_REMOVED = 3;
- public static final int EVENT_VOLUME_STATE_CHANGED = 4;
-
- private Message mMessage;
-
- public StorageEvent(int what) {
- mMessage = Message.obtain();
- mMessage.what = what;
- mMessage.obj = this;
- }
-
- public Message getMessage() {
- return mMessage;
- }
- }
-
- /**
- * Message sent on a share availability change.
- */
- private class ShareAvailabilityChangedStorageEvent extends StorageEvent {
- public String method;
- public boolean available;
-
- public ShareAvailabilityChangedStorageEvent(String m, boolean a) {
- super(EVENT_SHARE_AVAILABILITY_CHANGED);
- method = m;
- available = a;
- }
- }
-
- /**
- * Message sent on media insertion
- */
- private class MediaInsertedStorageEvent extends StorageEvent {
- public String label;
- public String path;
- public int major;
- public int minor;
-
- public MediaInsertedStorageEvent(String l, String p, int maj, int min) {
- super(EVENT_MEDIA_INSERTED);
- label = l;
- path = p;
- major = maj;
- minor = min;
- }
- }
-
- /**
- * Message sent on media removal
- */
- private class MediaRemovedStorageEvent extends StorageEvent {
- public String label;
- public String path;
- public int major;
- public int minor;
- public boolean clean;
-
- public MediaRemovedStorageEvent(String l, String p, int maj, int min, boolean c) {
- super(EVENT_MEDIA_REMOVED);
- label = l;
- path = p;
- major = maj;
- minor = min;
- clean = c;
- }
- }
-
- /**
- * Message sent on volume state change
- */
- private class VolumeStateChangedStorageEvent extends StorageEvent {
- public String label;
- public String path;
- public String oldState;
- public String newState;
-
- public VolumeStateChangedStorageEvent(String l, String p, String oldS, String newS) {
- super(EVENT_VOLUME_STATE_CHANGED);
- label = l;
- path = p;
- oldState = oldS;
- newState = newS;
- }
- }
-
- /**
- * Private class containing sender and receiver code for StorageEvents
- */
- private class ListenerDelegate {
- final StorageEventListener mStorageEventListener;
- private final Handler mHandler;
-
- ListenerDelegate(StorageEventListener listener) {
- mStorageEventListener = listener;
- mHandler = new Handler(mTgtLooper) {
- @Override
- public void handleMessage(Message msg) {
- StorageEvent e = (StorageEvent) msg.obj;
-
- if (msg.what == StorageEvent.EVENT_SHARE_AVAILABILITY_CHANGED) {
- ShareAvailabilityChangedStorageEvent ev = (ShareAvailabilityChangedStorageEvent) e;
- mStorageEventListener.onShareAvailabilityChanged(ev.method, ev.available);
- } else if (msg.what == StorageEvent.EVENT_MEDIA_INSERTED) {
- MediaInsertedStorageEvent ev = (MediaInsertedStorageEvent) e;
- mStorageEventListener.onMediaInserted(ev.label, ev.path, ev.major, ev.minor);
- } else if (msg.what == StorageEvent.EVENT_MEDIA_REMOVED) {
- MediaRemovedStorageEvent ev = (MediaRemovedStorageEvent) e;
- mStorageEventListener.onMediaRemoved(ev.label, ev.path, ev.major, ev.minor, ev.clean);
- } else if (msg.what == StorageEvent.EVENT_VOLUME_STATE_CHANGED) {
- VolumeStateChangedStorageEvent ev = (VolumeStateChangedStorageEvent) e;
- mStorageEventListener.onVolumeStateChanged(ev.label, ev.path, ev.oldState, ev.newState);
- } else {
- Log.e(TAG, "Unsupported event " + msg.what);
- }
- }
- };
- }
-
- StorageEventListener getListener() {
- return mStorageEventListener;
- }
-
- void sendShareAvailabilityChanged(String method, boolean available) {
- ShareAvailabilityChangedStorageEvent e = new ShareAvailabilityChangedStorageEvent(method, available);
- mHandler.sendMessage(e.getMessage());
- }
-
- void sendMediaInserted(String label, String path, int major, int minor) {
- MediaInsertedStorageEvent e = new MediaInsertedStorageEvent(label, path, major, minor);
- mHandler.sendMessage(e.getMessage());
- }
-
- void sendMediaRemoved(String label, String path, int major, int minor, boolean clean) {
- MediaRemovedStorageEvent e = new MediaRemovedStorageEvent(label, path, major, minor, clean);
- mHandler.sendMessage(e.getMessage());
- }
-
- void sendVolumeStateChanged(String label, String path, String oldState, String newState) {
- VolumeStateChangedStorageEvent e = new VolumeStateChangedStorageEvent(label, path, oldState, newState);
- mHandler.sendMessage(e.getMessage());
- }
- }
-
- /**
- * {@hide}
- */
- public StorageManager(Looper tgtLooper) throws RemoteException {
- mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
- if (mMountService == null) {
- Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
- return;
- }
- mTgtLooper = tgtLooper;
- mBinderListener = new MountServiceBinderListener();
- mMountService.registerListener(mBinderListener);
- }
-
-
- /**
- * Registers a {@link android.storage.StorageEventListener StorageEventListener}.
- *
- * @param listener A {@link android.storage.StorageEventListener StorageEventListener} object.
- *
- */
- public void registerListener(StorageEventListener listener) {
- if (listener == null) {
- return;
- }
-
- synchronized (sListeners) {
- sListeners.add(new ListenerDelegate(listener));
- }
- }
-
- /**
- * Unregisters a {@link android.storage.StorageEventListener StorageEventListener}.
- *
- * @param listener A {@link android.storage.StorageEventListener StorageEventListener} object.
- *
- */
- public void unregisterListener(StorageEventListener listener) {
- if (listener == null) {
- return;
- }
- synchronized (sListeners) {
- final int size = sListeners.size();
- for (int i=0 ; i<size ; i++) {
- ListenerDelegate l = sListeners.get(i);
- if (l.getListener() == listener) {
- sListeners.remove(i);
- break;
- }
- }
- }
- }
-}
diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
index 2b07ae6..7e9bbd1 100644
--- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
+++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java
@@ -24,7 +24,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IMountService;
+import android.os.storage.IMountService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index 98fb236..24818a8 100755
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -24,7 +24,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IMountService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index c110f95..2f48499 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -32,7 +32,7 @@ import android.os.RemoteException;
import android.os.Power;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.IMountService;
+import android.os.storage.IMountService;
import com.android.internal.telephony.ITelephony;
import android.util.Log;
diff --git a/core/java/com/android/internal/app/StorageNotification.java b/core/java/com/android/internal/app/StorageNotification.java
index 27967fc..8876612 100644
--- a/core/java/com/android/internal/app/StorageNotification.java
+++ b/core/java/com/android/internal/app/StorageNotification.java
@@ -30,12 +30,12 @@ import android.content.res.Resources;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
-import android.os.IMountService;
+import android.os.storage.IMountService;
import android.os.Message;
-import android.os.MountServiceResultCode;
import android.os.ServiceManager;
-import android.storage.StorageEventListener;
-import android.storage.StorageManager;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageResultCode;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -43,7 +43,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-public class StorageNotification implements StorageEventListener {
+public class StorageNotification extends StorageEventListener {
private static final String TAG = "StorageNotification";
/**
@@ -69,72 +69,55 @@ public class StorageNotification implements StorageEventListener {
* <p>
* This is lazily created, so use {@link #setMediaStorageNotification()}.
*/
- private Notification mMediaStorageNotification;
-
- private boolean mShowSafeUnmountNotificationWhenUnmounted;
- private boolean mUmsAvailable;
- private IMountService mMountService; // XXX: This should go away soon
+ private Notification mMediaStorageNotification;
+ private boolean mUmsAvailable;
+ private StorageManager mStorageManager;
public StorageNotification(Context context) {
mContext = context;
- /*
- * XXX: This needs to be exposed via StorageManager
- */
- mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
- try {
- mUmsAvailable = mMountService.getShareMethodAvailable("ums");
- } catch (Exception e) {
- Log.e(TAG, "Failed to get ums availability", e);
- }
- }
-
- public void onShareAvailabilityChanged(String method, boolean available) {
- if (method.equals("ums")) {
- mUmsAvailable = available;
- /*
- * Even though we may have a UMS host connected, we the SD card
- * may not be in a state for export.
- */
- String st = Environment.getExternalStorageState();
- if (available && (st.equals(
- Environment.MEDIA_REMOVED) || st.equals(Environment.MEDIA_CHECKING))) {
- /*
- * No card or card being checked = don't display
- */
- available = false;
- }
-
- updateUsbMassStorageNotification(available);
- }
- }
-
- public void onMediaInserted(String label, String path, int major, int minor) {
+ mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+ mUmsAvailable = mStorageManager.isUsbMassStorageConnected();
+ Log.d(TAG, String.format( "Startup with UMS connection %s (media state %s)", mUmsAvailable,
+ Environment.getExternalStorageState()));
}
- public void onMediaRemoved(String label, String path, int major, int minor, boolean clean) {
+ /*
+ * @override com.android.os.storage.StorageEventListener
+ */
+ @Override
+ public void onUsbMassStorageConnectionChanged(boolean connected) {
+ mUmsAvailable = connected;
/*
- * Media removed - first clear the USB storage notification (if any)
+ * Even though we may have a UMS host connected, we the SD card
+ * may not be in a state for export.
*/
- updateUsbMassStorageNotification(false);
+ String st = Environment.getExternalStorageState();
- if (clean) {
- setMediaStorageNotification(
- com.android.internal.R.string.ext_media_nomedia_notification_title,
- com.android.internal.R.string.ext_media_nomedia_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard_usb,
- true, false, null);
- } else {
- setMediaStorageNotification(
- com.android.internal.R.string.ext_media_badremoval_notification_title,
- com.android.internal.R.string.ext_media_badremoval_notification_message,
- com.android.internal.R.drawable.stat_sys_warning,
- true, true, null);
+ Log.i(TAG, String.format("UMS connection changed to %s (media state %s)", connected, st));
+
+ if (connected && (st.equals(
+ Environment.MEDIA_REMOVED) || st.equals(Environment.MEDIA_CHECKING))) {
+ /*
+ * No card or card being checked = don't display
+ */
+ connected = false;
}
+ updateUsbMassStorageNotification(connected);
}
- public void onVolumeStateChanged(String label, String path, String oldState, String newState) {
+ /*
+ * @override com.android.os.storage.StorageEventListener
+ */
+ @Override
+ public void onStorageStateChanged(String path, String oldState, String newState) {
+ Log.i(TAG, String.format(
+ "Media {%s} state changed from {%s} -> {%s}", path, oldState, newState));
if (newState.equals(Environment.MEDIA_SHARED)) {
+ /*
+ * Storage is now shared. Modify the UMS notification
+ * for stopping UMS.
+ */
Intent intent = new Intent();
intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
@@ -143,26 +126,60 @@ public class StorageNotification implements StorageEventListener {
com.android.internal.R.string.usb_storage_stop_notification_message,
com.android.internal.R.drawable.stat_sys_warning, false, true, pi);
} else if (newState.equals(Environment.MEDIA_CHECKING)) {
+ /*
+ * Storage is now checking. Update media notification and disable
+ * UMS notification.
+ */
setMediaStorageNotification(
com.android.internal.R.string.ext_media_checking_notification_title,
com.android.internal.R.string.ext_media_checking_notification_message,
com.android.internal.R.drawable.stat_notify_sdcard_prepare, true, false, null);
updateUsbMassStorageNotification(false);
} else if (newState.equals(Environment.MEDIA_MOUNTED)) {
+ /*
+ * Storage is now mounted. Dismiss any media notifications,
+ * and enable UMS notification if connected.
+ */
setMediaStorageNotification(0, 0, 0, false, false, null);
updateUsbMassStorageNotification(mUmsAvailable);
} else if (newState.equals(Environment.MEDIA_UNMOUNTED)) {
- if (mShowSafeUnmountNotificationWhenUnmounted) {
- setMediaStorageNotification(
- com.android.internal.R.string.ext_media_safe_unmount_notification_title,
- com.android.internal.R.string.ext_media_safe_unmount_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard, true, true, null);
- mShowSafeUnmountNotificationWhenUnmounted = false;
+ /*
+ * Storage is now unmounted. We may have been unmounted
+ * because the user is enabling/disabling UMS, in which case we don't
+ * want to display the 'safe to unmount' notification.
+ */
+ if (!mStorageManager.isUsbMassStorageEnabled()) {
+ if (oldState.equals(Environment.MEDIA_SHARED)) {
+ /*
+ * The unmount was due to UMS being enabled. Dismiss any
+ * media notifications, and enable UMS notification if connected
+ */
+ setMediaStorageNotification(0, 0, 0, false, false, null);
+ updateUsbMassStorageNotification(mUmsAvailable);
+ } else {
+ /*
+ * Show safe to unmount media notification, and enable UMS
+ * notification if connected.
+ */
+ setMediaStorageNotification(
+ com.android.internal.R.string.ext_media_safe_unmount_notification_title,
+ com.android.internal.R.string.ext_media_safe_unmount_notification_message,
+ com.android.internal.R.drawable.stat_notify_sdcard, true, true, null);
+ updateUsbMassStorageNotification(mUmsAvailable);
+ }
} else {
+ /*
+ * The unmount was due to UMS being enabled. Dismiss any
+ * media notifications, and disable the UMS notification
+ */
setMediaStorageNotification(0, 0, 0, false, false, null);
+ updateUsbMassStorageNotification(false);
}
- updateUsbMassStorageNotification(mUmsAvailable);
} else if (newState.equals(Environment.MEDIA_NOFS)) {
+ /*
+ * Storage has no filesystem. Show blank media notification,
+ * and enable UMS notification if connected.
+ */
Intent intent = new Intent();
intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class);
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
@@ -173,6 +190,10 @@ public class StorageNotification implements StorageEventListener {
com.android.internal.R.drawable.stat_notify_sdcard_usb, true, false, pi);
updateUsbMassStorageNotification(mUmsAvailable);
} else if (newState.equals(Environment.MEDIA_UNMOUNTABLE)) {
+ /*
+ * Storage is corrupt. Show corrupt media notification,
+ * and enable UMS notification if connected.
+ */
Intent intent = new Intent();
intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class);
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
@@ -182,6 +203,30 @@ public class StorageNotification implements StorageEventListener {
com.android.internal.R.string.ext_media_unmountable_notification_message,
com.android.internal.R.drawable.stat_notify_sdcard_usb, true, false, pi);
updateUsbMassStorageNotification(mUmsAvailable);
+ } else if (newState.equals(Environment.MEDIA_REMOVED)) {
+ /*
+ * Storage has been removed. Show nomedia media notification,
+ * and disable UMS notification regardless of connection state.
+ */
+ setMediaStorageNotification(
+ com.android.internal.R.string.ext_media_nomedia_notification_title,
+ com.android.internal.R.string.ext_media_nomedia_notification_message,
+ com.android.internal.R.drawable.stat_notify_sdcard_usb,
+ true, false, null);
+ updateUsbMassStorageNotification(false);
+ } else if (newState.equals(Environment.MEDIA_BAD_REMOVAL)) {
+ /*
+ * Storage has been removed unsafely. Show bad removal media notification,
+ * and disable UMS notification regardless of connection state.
+ */
+ setMediaStorageNotification(
+ com.android.internal.R.string.ext_media_badremoval_notification_title,
+ com.android.internal.R.string.ext_media_badremoval_notification_message,
+ com.android.internal.R.drawable.stat_sys_warning,
+ true, true, null);
+ updateUsbMassStorageNotification(false);
+ } else {
+ Log.w(TAG, String.format("Ignoring unknown state {%s}", newState));
}
}
diff --git a/core/java/com/android/internal/app/TetherActivity.java b/core/java/com/android/internal/app/TetherActivity.java
index 2b93dbc..cb268b3 100644
--- a/core/java/com/android/internal/app/TetherActivity.java
+++ b/core/java/com/android/internal/app/TetherActivity.java
@@ -25,7 +25,6 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IMountService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
diff --git a/core/java/com/android/internal/app/UsbStorageActivity.java b/core/java/com/android/internal/app/UsbStorageActivity.java
index 34ae2b4..991f04b 100644
--- a/core/java/com/android/internal/app/UsbStorageActivity.java
+++ b/core/java/com/android/internal/app/UsbStorageActivity.java
@@ -25,8 +25,9 @@ import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Environment;
-import android.os.IMountService;
-import android.os.MountServiceResultCode;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageResultCode;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -35,6 +36,7 @@ import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.view.View;
+import android.util.Log;
/**
* This activity is shown to the user for him/her to enable USB mass storage
@@ -42,11 +44,13 @@ import android.view.View;
* dialog style. It will be launched from a notification.
*/
public class UsbStorageActivity extends Activity {
+ private static final String TAG = "UsbStorageActivity";
private Button mMountButton;
private Button mUnmountButton;
private TextView mBanner;
private TextView mMessage;
private ImageView mIcon;
+ private StorageManager mStorageManager = null;
/** Used to detect when the USB cable is unplugged, so we can call finish() */
private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
@@ -57,11 +61,30 @@ public class UsbStorageActivity extends Activity {
}
}
};
+
+ private StorageEventListener mStorageListener = new StorageEventListener() {
+ @Override
+ public void onStorageStateChanged(String path, String oldState, String newState) {
+ if (newState.equals(Environment.MEDIA_SHARED)) {
+ switchDisplay(true);
+ } else {
+ switchDisplay(false);
+ }
+ }
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (mStorageManager == null) {
+ mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
+ if (mStorageManager == null) {
+ Log.w(TAG, "Failed to get StorageManager");
+ }
+ mStorageManager.registerListener(mStorageListener);
+ }
+
setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
setContentView(com.android.internal.R.layout.usb_storage_activity);
@@ -74,9 +97,11 @@ public class UsbStorageActivity extends Activity {
mMountButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
- mountAsUsbStorage();
- // TODO: replace with forthcoming MountService callbacks
- switchDisplay(true);
+ int rc = mStorageManager.enableUsbMassStorage();
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("UMS enable failed (%d)", rc));
+ showSharingError();
+ }
}
});
@@ -84,9 +109,11 @@ public class UsbStorageActivity extends Activity {
mUnmountButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
- stopUsbStorage();
- // TODO: replace with forthcoming MountService callbacks
- switchDisplay(false);
+ int rc = mStorageManager.disableUsbMassStorage();
+ if (rc != StorageResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("UMS disable failed (%d)", rc));
+ showStoppingError();
+ }
}
});
}
@@ -112,19 +139,11 @@ public class UsbStorageActivity extends Activity {
super.onResume();
registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-
- boolean umsOn = false;
try {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService != null) {
- umsOn = mountService.getVolumeShared(
- Environment.getExternalStorageDirectory().getPath(), "ums");
- }
- } catch (android.os.RemoteException exc) {
- // pass
+ switchDisplay(mStorageManager.isUsbMassStorageEnabled());
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed to read UMS enable state", ex);
}
- switchDisplay(umsOn);
}
@Override
@@ -134,42 +153,6 @@ public class UsbStorageActivity extends Activity {
unregisterReceiver(mBatteryReceiver);
}
- private void mountAsUsbStorage() {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService == null) {
- showSharingError();
- return;
- }
-
- try {
- if (mountService.shareVolume(
- Environment.getExternalStorageDirectory().getPath(), "ums") !=
- MountServiceResultCode.OperationSucceeded) {
- showSharingError();
- }
- } catch (RemoteException e) {
- showSharingError();
- }
- }
-
- private void stopUsbStorage() {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService == null) {
- showStoppingError();
- return;
- }
-
- try {
- mountService.unshareVolume(
- Environment.getExternalStorageDirectory().getPath(), "ums");
- } catch (RemoteException e) {
- showStoppingError();
- return;
- }
- }
-
private void handleBatteryChanged(Intent intent) {
int pluggedType = intent.getIntExtra("plugged", 0);
if (pluggedType == 0) {