OSDN Git Service

b/2498180 b/2568119 Retry if BT dock disconnects unexpectedly
[android-x86/packages-apps-Settings.git] / src / com / android / settings / bluetooth / DockEventReceiver.java
index 261ec1d..6d11972 100644 (file)
 
 package com.android.settings.bluetooth;
 
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+
 import android.app.Service;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.PowerManager;
 import android.util.Log;
 
 public class DockEventReceiver extends BroadcastReceiver {
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = DockService.DEBUG;
 
     private static final String TAG = "DockEventReceiver";
 
@@ -35,16 +41,19 @@ public class DockEventReceiver extends BroadcastReceiver {
 
     private static final int EXTRA_INVALID = -1234;
 
-    static final Object mStartingServiceSync = new Object();
+    private static final Object mStartingServiceSync = new Object();
+
+    private static final long WAKELOCK_TIMEOUT = 5000;
 
-    static PowerManager.WakeLock mStartingService;
+    private static PowerManager.WakeLock mStartingService;
 
     @Override
     public void onReceive(Context context, Intent intent) {
         if (intent == null)
             return;
 
-        int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, EXTRA_INVALID);
+        int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, intent.getIntExtra(
+                BluetoothAdapter.EXTRA_STATE, EXTRA_INVALID));
         BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 
         if (DEBUG) {
@@ -71,6 +80,61 @@ public class DockEventReceiver extends BroadcastReceiver {
                     if (DEBUG) Log.e(TAG, "Unknown state");
                     break;
             }
+        } else if (BluetoothHeadset.ACTION_STATE_CHANGED.equals(intent.getAction())) {
+            /*
+             *  Reconnect to the dock if:
+             *  1) it is a dock
+             *  2) it is disconnected
+             *  3) the disconnect is initiated remotely
+             *  4) the dock is still docked (check can only be done in the Service)
+             */
+            if (device == null) {
+                if (DEBUG) Log.d(TAG, "Device is missing");
+                return;
+            }
+
+            int newState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
+                    BluetoothHeadset.STATE_CONNECTED);
+            if (newState != BluetoothHeadset.STATE_DISCONNECTED) return;
+
+            int source = intent.getIntExtra(BluetoothHeadset.EXTRA_DISCONNECT_INITIATOR,
+                    BluetoothHeadset.LOCAL_DISCONNECT);
+            if (source != BluetoothHeadset.REMOTE_DISCONNECT) return;
+
+            // Too bad, the dock state can't be checked from a BroadcastReceiver.
+            Intent i = new Intent(intent);
+            i.setClass(context, DockService.class);
+            beginStartingService(context, i);
+
+        } else if (BluetoothA2dp.ACTION_SINK_STATE_CHANGED.equals(intent.getAction())) {
+            /*
+             *  Reconnect to the dock if:
+             *  1) it is a dock
+             *  2) it is an unexpected disconnect i.e. didn't go through disconnecting state
+             *  3) the dock is still docked (check can only be done in the Service)
+             */
+            if (device == null) {
+                if (DEBUG) Log.d(TAG, "Device is missing");
+                return;
+            }
+
+            int newState = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE, 0);
+            int oldState = intent.getIntExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, 0);
+            if (newState == BluetoothA2dp.STATE_DISCONNECTED &&
+                    oldState != BluetoothA2dp.STATE_DISCONNECTING) {
+                // Too bad, the dock state can't be checked from a BroadcastReceiver.
+                Intent i = new Intent(intent);
+                i.setClass(context, DockService.class);
+                beginStartingService(context, i);
+            }
+
+        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
+            int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+            if (btState != BluetoothAdapter.STATE_TURNING_ON) {
+                Intent i = new Intent(intent);
+                i.setClass(context, DockService.class);
+                beginStartingService(context, i);
+            }
         }
     }
 
@@ -84,14 +148,12 @@ public class DockEventReceiver extends BroadcastReceiver {
                 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
                 mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                         "StartingDockService");
-                mStartingService.setReferenceCounted(false);
             }
 
-            mStartingService.acquire();
+            mStartingService.acquire(WAKELOCK_TIMEOUT);
 
             if (context.startService(intent) == null) {
                 Log.e(TAG, "Can't start DockService");
-                mStartingService.release();
             }
         }
     }
@@ -104,9 +166,7 @@ public class DockEventReceiver extends BroadcastReceiver {
         synchronized (mStartingServiceSync) {
             if (mStartingService != null) {
                 if (DEBUG) Log.d(TAG, "stopSelf id = "+ startId);
-                if (service.stopSelfResult(startId)) {
-                    mStartingService.release();
-                }
+                service.stopSelfResult(startId);
             }
         }
     }