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>
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;
+    }
+}