DO NOT MERGE Tethering: Delay 1000ms before processing USB disconnect events

This change is already in master

On some devices, switching the USB configuration to enable RNDIS can
result in multiple USB disconnect/reconnect events being generated.

Change-Id: I14b02aaca11bb708f6b3334e41a2f4d4fa7b7296
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index eb0a8a9..1bc5e4b 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -35,6 +35,7 @@
 import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
@@ -110,6 +111,14 @@
     private boolean mUsbMassStorageOff;  // track the status of USB Mass Storage
     private boolean mUsbConnected;       // track the status of USB connection
 
+    // mUsbHandler message
+    static final int USB_STATE_CHANGE = 1;
+    static final int USB_DISCONNECTED = 0;
+    static final int USB_CONNECTED = 1;
+
+    // Time to delay before processing USB disconnect events
+    static final long USB_DISCONNECT_DELAY = 1000;
+
     public Tethering(Context context, Looper looper) {
         Log.d(TAG, "Tethering starting");
         mContext = context;
@@ -421,12 +430,25 @@
         }
     }
 
+    private Handler mUsbHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            mUsbConnected = (msg.arg1 == USB_CONNECTED);
+            updateUsbStatus();
+        }
+    };
+
     private class StateReceiver extends BroadcastReceiver {
         public void onReceive(Context content, Intent intent) {
             String action = intent.getAction();
             if (action.equals(Usb.ACTION_USB_STATE)) {
-                mUsbConnected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
-                updateUsbStatus();
+                // process connect events immediately, but delay handling disconnects
+                // to debounce USB configuration changes
+                boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
+                Message msg = Message.obtain(mUsbHandler, USB_STATE_CHANGE,
+                        (connected ? USB_CONNECTED : USB_DISCONNECTED), 0);
+                mUsbHandler.removeMessages(USB_STATE_CHANGE);
+                mUsbHandler.sendMessageDelayed(msg, connected ? 0 : USB_DISCONNECT_DELAY);
             } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
                 mUsbMassStorageOff = false;
                 updateUsbStatus();