am 606d591a: Merge "Add new Usb.ACTION_USB_STATE sticky broadcast for monitoring USB connect state" into gingerbread

Merge commit '606d591afee24e31e3885a7330638893db1710f5' into gingerbread-plus-aosp

* commit '606d591afee24e31e3885a7330638893db1710f5':
  Add new Usb.ACTION_USB_STATE sticky broadcast for monitoring USB connect state
diff --git a/core/java/android/hardware/Usb.java b/core/java/android/hardware/Usb.java
index e9c2cf7..57271d4 100644
--- a/core/java/android/hardware/Usb.java
+++ b/core/java/android/hardware/Usb.java
@@ -39,6 +39,27 @@
     public static final String ACTION_USB_DISCONNECTED =
             "android.hardware.action.USB_DISCONNECTED";
 
+   /**
+     * Broadcast Action:  A sticky broadcast for USB state change events.
+     *
+     * This is a sticky broadcast for clients that are interested in both USB connect and
+     * disconnect events.  If you are only concerned with one or the other, you can use
+     * {@link #ACTION_USB_CONNECTED} or {@link #ACTION_USB_DISCONNECTED} to avoid receiving
+     * unnecessary broadcasts.  The boolean {@link #USB_CONNECTED} extra indicates whether
+     * USB is connected or disconnected.
+     * The extras bundle will also contain name/value pairs with the name of the function
+     * and a value of either {@link #USB_FUNCTION_ENABLED} or {@link #USB_FUNCTION_DISABLED}.
+     * Possible USB function names include {@link #USB_FUNCTION_MASS_STORAGE},
+     * {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS} and {@link #USB_FUNCTION_MTP}.
+     */
+    public static final String ACTION_USB_STATE =
+            "android.hardware.action.USB_STATE";
+
+    /**
+     * Boolean extra indicating whether USB is connected or disconnected.
+     * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
+     */
+    public static final String USB_CONNECTED = "connected";
 
     /**
      * Name of the USB mass storage USB function.
diff --git a/services/java/com/android/server/UsbObserver.java b/services/java/com/android/server/UsbObserver.java
index 3993a7f..d08fe9b 100644
--- a/services/java/com/android/server/UsbObserver.java
+++ b/services/java/com/android/server/UsbObserver.java
@@ -159,6 +159,16 @@
     }
 
     private final Handler mHandler = new Handler() {
+        private void addEnabledFunctions(Intent intent) {
+            // include state of all USB functions in our extras
+            for (int i = 0; i < mEnabledFunctions.size(); i++) {
+                intent.putExtra(mEnabledFunctions.get(i), Usb.USB_FUNCTION_ENABLED);
+            }
+            for (int i = 0; i < mDisabledFunctions.size(); i++) {
+                intent.putExtra(mDisabledFunctions.get(i), Usb.USB_FUNCTION_DISABLED);
+            }
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -174,21 +184,21 @@
                         // Send an Intent containing connected/disconnected state
                         // and the enabled/disabled state of all USB functions
                         Intent intent;
-                        if (mUsbConfig != 0) {
+                        boolean usbConnected = (mUsbConfig != 0);
+                        if (usbConnected) {
                             intent = new Intent(Usb.ACTION_USB_CONNECTED);
-
-                            // include state of all USB functions in our extras
-                            for (int i = 0; i < mEnabledFunctions.size(); i++) {
-                                intent.putExtra(mEnabledFunctions.get(i), Usb.USB_FUNCTION_ENABLED);
-                            }
-                            for (int i = 0; i < mDisabledFunctions.size(); i++) {
-                                intent.putExtra(mDisabledFunctions.get(i), Usb.USB_FUNCTION_DISABLED);
-                            }
+                            addEnabledFunctions(intent);
                         } else {
                             intent = new Intent(Usb.ACTION_USB_DISCONNECTED);
                         }
+                        mContext.sendBroadcast(intent);
 
-                        mContext.sendBroadcast(intent, android.Manifest.permission.ACCESS_USB);
+                        // send a sticky broadcast for clients interested in both connect and disconnect
+                        intent = new Intent(Usb.ACTION_USB_STATE);
+                        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+                        intent.putExtra(Usb.USB_CONNECTED, usbConnected);
+                        addEnabledFunctions(intent);
+                        mContext.sendStickyBroadcast(intent);
                     }
                     break;
             }