1df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan/* 2df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Copyright (C) 2009 The Android Open Source Project 3df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * 4df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 5df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * you may not use this file except in compliance with the License. 6df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * You may obtain a copy of the License at 7df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * 8df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * http://www.apache.org/licenses/LICENSE-2.0 9df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * 10df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * Unless required by applicable law or agreed to in writing, software 11df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, 12df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * See the License for the specific language governing permissions and 14df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan * limitations under the License. 15df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan */ 16df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 17df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanpackage com.android.settings.bluetooth; 18df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 193fe86a346cdcd41fd9498591571d8b512a130240Michael Chanimport com.android.settings.R; 2057d5585595810044e7727d4303214f69ff2d77d4Michael Chanimport com.android.settings.bluetooth.LocalBluetoothProfileManager.ServiceListener; 213fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 22df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.app.AlertDialog; 23df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.app.Notification; 24df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.app.Service; 25845e740fc63657438b9085376c8e7d60d8334a72Michael Chanimport android.bluetooth.BluetoothA2dp; 26df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.bluetooth.BluetoothAdapter; 27df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.bluetooth.BluetoothDevice; 28845e740fc63657438b9085376c8e7d60d8334a72Michael Chanimport android.bluetooth.BluetoothHeadset; 29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothProfile; 30df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.content.DialogInterface; 31df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.content.Intent; 32146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chanimport android.content.IntentFilter; 333fe86a346cdcd41fd9498591571d8b512a130240Michael Chanimport android.content.SharedPreferences; 34df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.os.Handler; 35df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.os.HandlerThread; 36df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.os.IBinder; 37df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.os.Looper; 38df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.os.Message; 39f892bc856c6780187db62681d59ca538a173590fEric Laurentimport android.provider.Settings; 40df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.util.Log; 41df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.view.LayoutInflater; 42df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.view.View; 43df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.view.WindowManager; 44df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.widget.CheckBox; 45df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chanimport android.widget.CompoundButton; 46df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 47436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.Collection; 48845e740fc63657438b9085376c8e7d60d8334a72Michael Chanimport java.util.List; 493fe86a346cdcd41fd9498591571d8b512a130240Michael Chanimport java.util.Set; 50845e740fc63657438b9085376c8e7d60d8334a72Michael Chan 51436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambypublic final class DockService extends Service implements ServiceListener { 52df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 53df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final String TAG = "DockService"; 54df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 55845e740fc63657438b9085376c8e7d60d8334a72Michael Chan static final boolean DEBUG = false; 56df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 57df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Time allowed for the device to be undocked and redocked without severing 58df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // the bluetooth connection 59df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final long UNDOCKED_GRACE_PERIOD = 1000; 60df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 613fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // Time allowed for the device to be undocked and redocked without turning 623fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // off Bluetooth 633fe86a346cdcd41fd9498591571d8b512a130240Michael Chan private static final long DISABLE_BT_GRACE_PERIOD = 2000; 643fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 65df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Msg for user wanting the UI to setup the dock 66df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final int MSG_TYPE_SHOW_UI = 111; 67146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 68df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Msg for device docked event 69df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final int MSG_TYPE_DOCKED = 222; 70146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 71df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Msg for device undocked event 72df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final int MSG_TYPE_UNDOCKED_TEMPORARY = 333; 73146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 74df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Msg for undocked command to be process after UNDOCKED_GRACE_PERIOD millis 75df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // since MSG_TYPE_UNDOCKED_TEMPORARY 76df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private static final int MSG_TYPE_UNDOCKED_PERMANENT = 444; 77df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 783fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // Msg for disabling bt after DISABLE_BT_GRACE_PERIOD millis since 793fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // MSG_TYPE_UNDOCKED_PERMANENT 803fe86a346cdcd41fd9498591571d8b512a130240Michael Chan private static final int MSG_TYPE_DISABLE_BT = 555; 813fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 823fe86a346cdcd41fd9498591571d8b512a130240Michael Chan private static final String SHARED_PREFERENCES_NAME = "dock_settings"; 833fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final String KEY_DISABLE_BT_WHEN_UNDOCKED = "disable_bt_when_undock"; 853fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final String KEY_DISABLE_BT = "disable_bt"; 87c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan 88436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final String KEY_CONNECT_RETRY_COUNT = "connect_retry_count"; 89732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 90732c1dad5a4871597652f17986b7a602897e5a76Michael Chan /* 91732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * If disconnected unexpectedly, reconnect up to 6 times. Each profile counts 92732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * as one time so it's only 3 times for both profiles on the car dock. 93732c1dad5a4871597652f17986b7a602897e5a76Michael Chan */ 94732c1dad5a4871597652f17986b7a602897e5a76Michael Chan private static final int MAX_CONNECT_RETRY = 6; 95732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 963fe86a346cdcd41fd9498591571d8b512a130240Michael Chan private static final int INVALID_STARTID = -100; 973fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 98df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Created in OnCreate() 99df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private volatile Looper mServiceLooper; 100df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private volatile ServiceHandler mServiceHandler; 10157d5585595810044e7727d4303214f69ff2d77d4Michael Chan private Runnable mRunnable; 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private LocalBluetoothAdapter mLocalAdapter; 103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private CachedBluetoothDeviceManager mDeviceManager; 104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private LocalBluetoothProfileManager mProfileManager; 105df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 106df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Normally set after getting a docked event and unset when the connection 107df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // is severed. One exception is that mDevice could be null if the service 108df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // was started after the docked event. 109df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private BluetoothDevice mDevice; 110df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 111df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Created and used for the duration of the dialog 112df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private AlertDialog mDialog; 113436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private LocalBluetoothProfile[] mProfiles; 114df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private boolean[] mCheckedItems; 115df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private int mStartIdAssociatedWithDialog; 116df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 117146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan // Set while BT is being enabled. 118146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan private BluetoothDevice mPendingDevice; 119146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan private int mPendingStartId; 1203fe86a346cdcd41fd9498591571d8b512a130240Michael Chan private int mPendingTurnOnStartId = INVALID_STARTID; 121c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan private int mPendingTurnOffStartId = INVALID_STARTID; 122146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 123df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan @Override 124df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public void onCreate() { 125df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) Log.d(TAG, "onCreate"); 126df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this); 128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (manager == null) { 129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "Can't get LocalBluetoothManager: exiting"); 130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = manager.getBluetoothAdapter(); 134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager = manager.getCachedDeviceManager(); 135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = manager.getProfileManager(); 136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mProfileManager == null) { 137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.e(TAG, "Can't get LocalBluetoothProfileManager: exiting"); 138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 140df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 141df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan HandlerThread thread = new HandlerThread("DockService"); 142df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan thread.start(); 143df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 144df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mServiceLooper = thread.getLooper(); 145df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mServiceHandler = new ServiceHandler(mServiceLooper); 146df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 147df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 148df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan @Override 149df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public void onDestroy() { 150df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) Log.d(TAG, "onDestroy"); 15157d5585595810044e7727d4303214f69ff2d77d4Michael Chan mRunnable = null; 152df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (mDialog != null) { 153df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDialog.dismiss(); 154df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDialog = null; 155df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mProfileManager != null) { 157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager.removeServiceListener(this); 158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mServiceLooper != null) { 160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceLooper.quit(); 161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter = null; 164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDeviceManager = null; 165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager = null; 166436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceLooper = null; 167436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceHandler = null; 168df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 169df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 170df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan @Override 171df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public IBinder onBind(Intent intent) { 172df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // not supported 173df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return null; 174df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 175df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 176436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private SharedPreferences getPrefs() { 177436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE); 178436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 180df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan @Override 181df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public int onStartCommand(Intent intent, int flags, int startId) { 182436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) Log.d(TAG, "onStartCommand startId: " + startId + " flags: " + flags); 183df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 184df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (intent == null) { 185df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Nothing to process, stop. 186df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) Log.d(TAG, "START_NOT_STICKY - intent is null."); 187df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 188df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // NOTE: We MUST not call stopSelf() directly, since we need to 189df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // make sure the wake lock acquired by the Receiver is released. 190df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan DockEventReceiver.finishStartingService(this, startId); 191df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return START_NOT_STICKY; 192df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 193df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 194845e740fc63657438b9085376c8e7d60d8334a72Michael Chan if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) { 1953fe86a346cdcd41fd9498591571d8b512a130240Michael Chan handleBtStateChange(intent, startId); 196845e740fc63657438b9085376c8e7d60d8334a72Michael Chan return START_NOT_STICKY; 197845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } 198845e740fc63657438b9085376c8e7d60d8334a72Michael Chan 199732c1dad5a4871597652f17986b7a602897e5a76Michael Chan /* 200732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * This assumes that the intent sender has checked that this is a dock 201732c1dad5a4871597652f17986b7a602897e5a76Michael Chan * and that the intent is for a disconnect 202732c1dad5a4871597652f17986b7a602897e5a76Michael Chan */ 203436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final SharedPreferences prefs = getPrefs(); 2045809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) { 205732c1dad5a4871597652f17986b7a602897e5a76Michael Chan BluetoothDevice disconnectedDevice = intent 206732c1dad5a4871597652f17986b7a602897e5a76Michael Chan .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 207436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int retryCount = prefs.getInt(KEY_CONNECT_RETRY_COUNT, 0); 208732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (retryCount < MAX_CONNECT_RETRY) { 209436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby prefs.edit().putInt(KEY_CONNECT_RETRY_COUNT, retryCount + 1).apply(); 210436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby handleUnexpectedDisconnect(disconnectedDevice, mProfileManager.getHeadsetProfile(), startId); 211732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 212732c1dad5a4871597652f17986b7a602897e5a76Michael Chan return START_NOT_STICKY; 2135809d33296d60f54c7e93de2f45bd84579f70449Jaikumar Ganesh } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) { 214732c1dad5a4871597652f17986b7a602897e5a76Michael Chan BluetoothDevice disconnectedDevice = intent 215732c1dad5a4871597652f17986b7a602897e5a76Michael Chan .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 216732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 217436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int retryCount = prefs.getInt(KEY_CONNECT_RETRY_COUNT, 0); 218732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (retryCount < MAX_CONNECT_RETRY) { 219436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby prefs.edit().putInt(KEY_CONNECT_RETRY_COUNT, retryCount + 1).apply(); 220436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby handleUnexpectedDisconnect(disconnectedDevice, mProfileManager.getA2dpProfile(), startId); 221732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 222732c1dad5a4871597652f17986b7a602897e5a76Michael Chan return START_NOT_STICKY; 223732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 224732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 225df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan Message msg = parseIntent(intent); 226df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (msg == null) { 227df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Bad intent 228df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) Log.d(TAG, "START_NOT_STICKY - Bad intent."); 229df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan DockEventReceiver.finishStartingService(this, startId); 230df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return START_NOT_STICKY; 231df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 232df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 233732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (msg.what == MSG_TYPE_DOCKED) { 234436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby prefs.edit().remove(KEY_CONNECT_RETRY_COUNT).apply(); 235732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 236732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 237df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan msg.arg2 = startId; 238df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan processMessage(msg); 239df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 240503c236db541b3d7c8278fa63afe4d1b792ac9a9Michael Chan return START_NOT_STICKY; 241df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 242df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 243df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private final class ServiceHandler extends Handler { 244436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private ServiceHandler(Looper looper) { 245df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan super(looper); 246df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 247df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 248df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan @Override 249df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan public void handleMessage(Message msg) { 250df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan processMessage(msg); 251df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 252df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 253df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 254df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // This method gets messages from both onStartCommand and mServiceHandler/mServiceLooper 255fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan private synchronized void processMessage(Message msg) { 256df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan int msgType = msg.what; 25757d5585595810044e7727d4303214f69ff2d77d4Michael Chan final int state = msg.arg1; 25857d5585595810044e7727d4303214f69ff2d77d4Michael Chan final int startId = msg.arg2; 2593fe86a346cdcd41fd9498591571d8b512a130240Michael Chan BluetoothDevice device = null; 2603fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if (msg.obj != null) { 2613fe86a346cdcd41fd9498591571d8b512a130240Michael Chan device = (BluetoothDevice) msg.obj; 2623fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 263df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 264df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if(DEBUG) Log.d(TAG, "processMessage: " + msgType + " state: " + state + " device = " 2653fe86a346cdcd41fd9498591571d8b512a130240Michael Chan + (device == null ? "null" : device.toString())); 266df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 267436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean deferFinishCall = false; 268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 269df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan switch (msgType) { 270df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case MSG_TYPE_SHOW_UI: 271f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device != null) { 272f892bc856c6780187db62681d59ca538a173590fEric Laurent createDialog(device, state, startId); 273f892bc856c6780187db62681d59ca538a173590fEric Laurent } 274df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 275df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 276df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case MSG_TYPE_DOCKED: 277436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby deferFinishCall = msgTypeDocked(device, state, startId); 278df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 279df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 280df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case MSG_TYPE_UNDOCKED_PERMANENT: 281436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby deferFinishCall = msgTypeUndockedPermanent(device, startId); 282df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 283df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 284df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case MSG_TYPE_UNDOCKED_TEMPORARY: 285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby msgTypeUndockedTemporary(device, state, startId); 286df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 2873fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 2883fe86a346cdcd41fd9498591571d8b512a130240Michael Chan case MSG_TYPE_DISABLE_BT: 289436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby deferFinishCall = msgTypeDisableBluetooth(startId); 2903fe86a346cdcd41fd9498591571d8b512a130240Michael Chan break; 291df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 292df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 2933fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if (mDialog == null && mPendingDevice == null && msgType != MSG_TYPE_UNDOCKED_TEMPORARY 2943fe86a346cdcd41fd9498591571d8b512a130240Michael Chan && !deferFinishCall) { 295df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // NOTE: We MUST not call stopSelf() directly, since we need to 296df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // make sure the wake lock acquired by the Receiver is released. 297436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockEventReceiver.finishStartingService(this, startId); 298df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 299df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 300df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 301436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private boolean msgTypeDisableBluetooth(int startId) { 302436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 303436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "BT DISABLE"); 304436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 305436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final SharedPreferences prefs = getPrefs(); 306436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mLocalAdapter.disable()) { 307436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby prefs.edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply(); 3083fe86a346cdcd41fd9498591571d8b512a130240Michael Chan return false; 309436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else { 310436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // disable() returned an error. Persist a flag to disable BT later 311436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby prefs.edit().putBoolean(KEY_DISABLE_BT, true).apply(); 312436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPendingTurnOffStartId = startId; 313436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if(DEBUG) { 314436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "disable failed. try again later " + startId); 315436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 3173fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 3193fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 320436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void msgTypeUndockedTemporary(BluetoothDevice device, int state, 321436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int startId) { 322436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Undocked event received. Queue a delayed msg to sever connection 323436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Message newMsg = mServiceHandler.obtainMessage(MSG_TYPE_UNDOCKED_PERMANENT, state, 324436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby startId, device); 325436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceHandler.sendMessageDelayed(newMsg, UNDOCKED_GRACE_PERIOD); 326436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 327436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 328436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private boolean msgTypeUndockedPermanent(BluetoothDevice device, int startId) { 329436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Grace period passed. Disconnect. 330436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby handleUndocked(device); 331f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device != null) { 332f892bc856c6780187db62681d59ca538a173590fEric Laurent final SharedPreferences prefs = getPrefs(); 333436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 334f892bc856c6780187db62681d59ca538a173590fEric Laurent if (DEBUG) { 335f892bc856c6780187db62681d59ca538a173590fEric Laurent Log.d(TAG, "DISABLE_BT_WHEN_UNDOCKED = " 336f892bc856c6780187db62681d59ca538a173590fEric Laurent + prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false)); 337f892bc856c6780187db62681d59ca538a173590fEric Laurent } 338436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 339f892bc856c6780187db62681d59ca538a173590fEric Laurent if (prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false)) { 340f892bc856c6780187db62681d59ca538a173590fEric Laurent if (hasOtherConnectedDevices(device)) { 341f892bc856c6780187db62681d59ca538a173590fEric Laurent // Don't disable BT if something is connected 342f892bc856c6780187db62681d59ca538a173590fEric Laurent prefs.edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply(); 343f892bc856c6780187db62681d59ca538a173590fEric Laurent } else { 344f892bc856c6780187db62681d59ca538a173590fEric Laurent // BT was disabled when we first docked 345f892bc856c6780187db62681d59ca538a173590fEric Laurent if (DEBUG) { 346f892bc856c6780187db62681d59ca538a173590fEric Laurent Log.d(TAG, "QUEUED BT DISABLE"); 347f892bc856c6780187db62681d59ca538a173590fEric Laurent } 348f892bc856c6780187db62681d59ca538a173590fEric Laurent // Queue a delayed msg to disable BT 349f892bc856c6780187db62681d59ca538a173590fEric Laurent Message newMsg = mServiceHandler.obtainMessage( 350f892bc856c6780187db62681d59ca538a173590fEric Laurent MSG_TYPE_DISABLE_BT, 0, startId, null); 351f892bc856c6780187db62681d59ca538a173590fEric Laurent mServiceHandler.sendMessageDelayed(newMsg, 352f892bc856c6780187db62681d59ca538a173590fEric Laurent DISABLE_BT_GRACE_PERIOD); 353f892bc856c6780187db62681d59ca538a173590fEric Laurent return true; 354436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 355436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 356436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 357436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 358436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 359436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 360436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private boolean msgTypeDocked(BluetoothDevice device, final int state, 361436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final int startId) { 362436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 363436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO figure out why hasMsg always returns false if device 364436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // is supplied 365436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "1 Has undock perm msg = " 366436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby + mServiceHandler.hasMessages(MSG_TYPE_UNDOCKED_PERMANENT, mDevice)); 367436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "2 Has undock perm msg = " 368436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby + mServiceHandler.hasMessages(MSG_TYPE_UNDOCKED_PERMANENT, device)); 369436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 370436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 371436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceHandler.removeMessages(MSG_TYPE_UNDOCKED_PERMANENT); 372436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mServiceHandler.removeMessages(MSG_TYPE_DISABLE_BT); 373436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby getPrefs().edit().remove(KEY_DISABLE_BT).apply(); 374436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 375f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device != null) { 376f892bc856c6780187db62681d59ca538a173590fEric Laurent if (!device.equals(mDevice)) { 377f892bc856c6780187db62681d59ca538a173590fEric Laurent if (mDevice != null) { 378f892bc856c6780187db62681d59ca538a173590fEric Laurent // Not expected. Cleanup/undock existing 379f892bc856c6780187db62681d59ca538a173590fEric Laurent handleUndocked(mDevice); 380f892bc856c6780187db62681d59ca538a173590fEric Laurent } 381436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 382f892bc856c6780187db62681d59ca538a173590fEric Laurent mDevice = device; 383f892bc856c6780187db62681d59ca538a173590fEric Laurent 384f892bc856c6780187db62681d59ca538a173590fEric Laurent // Register first in case LocalBluetoothProfileManager 385f892bc856c6780187db62681d59ca538a173590fEric Laurent // becomes ready after isManagerReady is called and it 386f892bc856c6780187db62681d59ca538a173590fEric Laurent // would be too late to register a service listener. 387f892bc856c6780187db62681d59ca538a173590fEric Laurent mProfileManager.addServiceListener(this); 388f892bc856c6780187db62681d59ca538a173590fEric Laurent if (mProfileManager.isManagerReady()) { 389f892bc856c6780187db62681d59ca538a173590fEric Laurent handleDocked(device, state, startId); 390f892bc856c6780187db62681d59ca538a173590fEric Laurent // Not needed after all 391f892bc856c6780187db62681d59ca538a173590fEric Laurent mProfileManager.removeServiceListener(this); 392f892bc856c6780187db62681d59ca538a173590fEric Laurent } else { 393f892bc856c6780187db62681d59ca538a173590fEric Laurent final BluetoothDevice d = device; 394f892bc856c6780187db62681d59ca538a173590fEric Laurent mRunnable = new Runnable() { 395f892bc856c6780187db62681d59ca538a173590fEric Laurent public void run() { 396f892bc856c6780187db62681d59ca538a173590fEric Laurent handleDocked(d, state, startId); // FIXME: WTF runnable here? 397f892bc856c6780187db62681d59ca538a173590fEric Laurent } 398f892bc856c6780187db62681d59ca538a173590fEric Laurent }; 399f892bc856c6780187db62681d59ca538a173590fEric Laurent return true; 400f892bc856c6780187db62681d59ca538a173590fEric Laurent } 401f892bc856c6780187db62681d59ca538a173590fEric Laurent } 402f892bc856c6780187db62681d59ca538a173590fEric Laurent } else { 403f892bc856c6780187db62681d59ca538a173590fEric Laurent // display dialog to enable dock for media audio only in the case of low end docks and 404f892bc856c6780187db62681d59ca538a173590fEric Laurent // if not already selected by user 405f892bc856c6780187db62681d59ca538a173590fEric Laurent int dockAudioMediaEnabled = Settings.Global.getInt(getContentResolver(), 406f892bc856c6780187db62681d59ca538a173590fEric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, -1); 407f892bc856c6780187db62681d59ca538a173590fEric Laurent if (dockAudioMediaEnabled == -1 && 408f892bc856c6780187db62681d59ca538a173590fEric Laurent state == Intent.EXTRA_DOCK_STATE_LE_DESK) { 409f892bc856c6780187db62681d59ca538a173590fEric Laurent handleDocked(null, state, startId); 410436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 411436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 412436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 413436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 414436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 415436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 416436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby synchronized boolean hasOtherConnectedDevices(BluetoothDevice dock) { 417436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Collection<CachedBluetoothDevice> cachedDevices = mDeviceManager.getCachedDevicesCopy(); 418436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Set<BluetoothDevice> btDevices = mLocalAdapter.getBondedDevices(); 419436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (btDevices == null || cachedDevices == null || btDevices.isEmpty()) { 420436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return false; 421436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 422436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if(DEBUG) { 423436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "btDevices = " + btDevices.size()); 424436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "cachedDeviceUIs = " + cachedDevices.size()); 425436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 426436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 427436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (CachedBluetoothDevice deviceUI : cachedDevices) { 428436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice btDevice = deviceUI.getDevice(); 429436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!btDevice.equals(dock) && btDevices.contains(btDevice) && deviceUI 430436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby .isConnected()) { 431436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if(DEBUG) Log.d(TAG, "connected deviceUI = " + deviceUI.getName()); 4323fe86a346cdcd41fd9498591571d8b512a130240Michael Chan return true; 4333fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 4343fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 4353fe86a346cdcd41fd9498591571d8b512a130240Michael Chan return false; 4363fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 4373fe86a346cdcd41fd9498591571d8b512a130240Michael Chan 438df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan private Message parseIntent(Intent intent) { 439df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 440df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, -1234); 441df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 442df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) { 443df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan Log.d(TAG, "Action: " + intent.getAction() + " State:" + state 4442036ebd8896bbabbbe04db34c9e7d8a1be6fe32aMatthew Xie + " Device: " + (device == null ? "null" : device.getAliasName())); 445df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 446df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 447df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan int msgType; 448df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan switch (state) { 449df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_UNDOCKED: 450df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan msgType = MSG_TYPE_UNDOCKED_TEMPORARY; 451df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 452df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_DESK: 453b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_HE_DESK: 454df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_CAR: 455f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device == null) { 456f892bc856c6780187db62681d59ca538a173590fEric Laurent Log.w(TAG, "device is null"); 457f892bc856c6780187db62681d59ca538a173590fEric Laurent return null; 458f892bc856c6780187db62681d59ca538a173590fEric Laurent } 459f892bc856c6780187db62681d59ca538a173590fEric Laurent /// Fall Through /// 460f892bc856c6780187db62681d59ca538a173590fEric Laurent case Intent.EXTRA_DOCK_STATE_LE_DESK: 461df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DockEventReceiver.ACTION_DOCK_SHOW_UI.equals(intent.getAction())) { 462f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device == null) { 463f892bc856c6780187db62681d59ca538a173590fEric Laurent Log.w(TAG, "device is null"); 464f892bc856c6780187db62681d59ca538a173590fEric Laurent return null; 465f892bc856c6780187db62681d59ca538a173590fEric Laurent } 466df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan msgType = MSG_TYPE_SHOW_UI; 467df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } else { 468df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan msgType = MSG_TYPE_DOCKED; 469df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 470df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 471df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan default: 472df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return null; 473df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 474df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 475df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return mServiceHandler.obtainMessage(msgType, state, 0, device); 476df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 477df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 478436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void createDialog(BluetoothDevice device, 479436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state, int startId) { 480436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mDialog != null) { 481436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Shouldn't normally happen 482436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDialog.dismiss(); 483436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDialog = null; 484436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 485436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDevice = device; 486df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan switch (state) { 487df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_CAR: 488df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_DESK: 489b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_LE_DESK: 490b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_HE_DESK: 491df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 492df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan default: 493436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 494df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 495df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 496df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan startForeground(0, new Notification()); 497df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 498f892bc856c6780187db62681d59ca538a173590fEric Laurent final AlertDialog.Builder ab = new AlertDialog.Builder(this); 499f892bc856c6780187db62681d59ca538a173590fEric Laurent View view; 500f892bc856c6780187db62681d59ca538a173590fEric Laurent LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE); 501df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 502f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device != null) { 503f892bc856c6780187db62681d59ca538a173590fEric Laurent // Device in a new dock. 504f892bc856c6780187db62681d59ca538a173590fEric Laurent boolean firstTime = 505f892bc856c6780187db62681d59ca538a173590fEric Laurent !LocalBluetoothPreferences.hasDockAutoConnectSetting(this, device.getAddress()); 506df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 507f892bc856c6780187db62681d59ca538a173590fEric Laurent CharSequence[] items = initBtSettings(device, state, firstTime); 508df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 509f892bc856c6780187db62681d59ca538a173590fEric Laurent ab.setTitle(getString(R.string.bluetooth_dock_settings_title)); 510df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 511f892bc856c6780187db62681d59ca538a173590fEric Laurent // Profiles 512f892bc856c6780187db62681d59ca538a173590fEric Laurent ab.setMultiChoiceItems(items, mCheckedItems, mMultiClickListener); 513f892bc856c6780187db62681d59ca538a173590fEric Laurent 514f892bc856c6780187db62681d59ca538a173590fEric Laurent // Remember this settings 515f892bc856c6780187db62681d59ca538a173590fEric Laurent view = inflater.inflate(R.layout.remember_dock_setting, null); 516f892bc856c6780187db62681d59ca538a173590fEric Laurent CheckBox rememberCheckbox = (CheckBox) view.findViewById(R.id.remember); 517f892bc856c6780187db62681d59ca538a173590fEric Laurent 518f892bc856c6780187db62681d59ca538a173590fEric Laurent // check "Remember setting" by default if no value was saved 519f892bc856c6780187db62681d59ca538a173590fEric Laurent boolean checked = firstTime || 520f892bc856c6780187db62681d59ca538a173590fEric Laurent LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress()); 521f892bc856c6780187db62681d59ca538a173590fEric Laurent rememberCheckbox.setChecked(checked); 522f892bc856c6780187db62681d59ca538a173590fEric Laurent rememberCheckbox.setOnCheckedChangeListener(mCheckedChangeListener); 523f892bc856c6780187db62681d59ca538a173590fEric Laurent if (DEBUG) { 524f892bc856c6780187db62681d59ca538a173590fEric Laurent Log.d(TAG, "Auto connect = " 525f892bc856c6780187db62681d59ca538a173590fEric Laurent + LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress())); 526f892bc856c6780187db62681d59ca538a173590fEric Laurent } 527f892bc856c6780187db62681d59ca538a173590fEric Laurent } else { 528f892bc856c6780187db62681d59ca538a173590fEric Laurent ab.setTitle(getString(R.string.bluetooth_dock_settings_title)); 529df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 530f892bc856c6780187db62681d59ca538a173590fEric Laurent view = inflater.inflate(R.layout.dock_audio_media_enable_dialog, null); 531f892bc856c6780187db62681d59ca538a173590fEric Laurent CheckBox audioMediaCheckbox = 532f892bc856c6780187db62681d59ca538a173590fEric Laurent (CheckBox) view.findViewById(R.id.dock_audio_media_enable_cb); 533f892bc856c6780187db62681d59ca538a173590fEric Laurent 534f892bc856c6780187db62681d59ca538a173590fEric Laurent boolean checked = Settings.Global.getInt(getContentResolver(), 535f892bc856c6780187db62681d59ca538a173590fEric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1; 536f892bc856c6780187db62681d59ca538a173590fEric Laurent 537f892bc856c6780187db62681d59ca538a173590fEric Laurent audioMediaCheckbox.setChecked(checked); 538f892bc856c6780187db62681d59ca538a173590fEric Laurent audioMediaCheckbox.setOnCheckedChangeListener(mCheckedChangeListener); 539f892bc856c6780187db62681d59ca538a173590fEric Laurent } 540f892bc856c6780187db62681d59ca538a173590fEric Laurent 541f892bc856c6780187db62681d59ca538a173590fEric Laurent float pixelScaleFactor = getResources().getDisplayMetrics().density; 542df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan int viewSpacingLeft = (int) (14 * pixelScaleFactor); 543df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan int viewSpacingRight = (int) (14 * pixelScaleFactor); 544df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan ab.setView(view, viewSpacingLeft, 0 /* top */, viewSpacingRight, 0 /* bottom */); 545df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 546df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Ok Button 547436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ab.setPositiveButton(getString(android.R.string.ok), mClickListener); 548df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 549df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mStartIdAssociatedWithDialog = startId; 550df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDialog = ab.create(); 551ae3311e5bd7b146eb4e1bc6310cbaba051776fb4Michael Chan mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 552436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDialog.setOnDismissListener(mDismissListener); 553df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDialog.show(); 554df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 555df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 556df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Called when the individual bt profiles are clicked. 557436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final DialogInterface.OnMultiChoiceClickListener mMultiClickListener = 558436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new DialogInterface.OnMultiChoiceClickListener() { 559436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onClick(DialogInterface dialog, int which, boolean isChecked) { 560436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 561436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "Item " + which + " changed to " + isChecked); 562436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 563436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCheckedItems[which] = isChecked; 564436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 565436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby }; 566436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 567df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 568df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Called when the "Remember" Checkbox is clicked 569436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final CompoundButton.OnCheckedChangeListener mCheckedChangeListener = 570436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new CompoundButton.OnCheckedChangeListener() { 571436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 572436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 573436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "onCheckedChanged: Remember Settings = " + isChecked); 574436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 575436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mDevice != null) { 576436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothPreferences.saveDockAutoConnectSetting( 577436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockService.this, mDevice.getAddress(), isChecked); 578f892bc856c6780187db62681d59ca538a173590fEric Laurent } else { 579f892bc856c6780187db62681d59ca538a173590fEric Laurent Settings.Global.putInt(getContentResolver(), 580f892bc856c6780187db62681d59ca538a173590fEric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, isChecked ? 1 : 0); 581436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 582436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 583436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby }; 584436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 585df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 586df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Called when the dialog is dismissed 587436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final DialogInterface.OnDismissListener mDismissListener = 588436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new DialogInterface.OnDismissListener() { 589436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onDismiss(DialogInterface dialog) { 590436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // NOTE: We MUST not call stopSelf() directly, since we need to 591436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // make sure the wake lock acquired by the Receiver is released. 592436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mPendingDevice == null) { 593436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockEventReceiver.finishStartingService( 594436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockService.this, mStartIdAssociatedWithDialog); 595436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 596436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby stopForeground(true); 597436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 598436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby }; 599df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 600df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Called when clicked on the OK button 601436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final DialogInterface.OnClickListener mClickListener = 602436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby new DialogInterface.OnClickListener() { 603436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onClick(DialogInterface dialog, int which) { 604436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (which == DialogInterface.BUTTON_POSITIVE 605436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby && mDevice != null) { 606436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (!LocalBluetoothPreferences 607436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby .hasDockAutoConnectSetting( 608436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockService.this, 609436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDevice.getAddress())) { 610436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothPreferences 611436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby .saveDockAutoConnectSetting( 612436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockService.this, 613436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mDevice.getAddress(), true); 614436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 615df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 616436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby applyBtSettings(mDevice, mStartIdAssociatedWithDialog); 617436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 618436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 619436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby }; 620df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 621436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private CharSequence[] initBtSettings(BluetoothDevice device, 622436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state, boolean firstTime) { 623df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // TODO Avoid hardcoding dock and profiles. Read from system properties 624e79f990490de49b39097433707c2bae6d8238330Jake Hamby int numOfProfiles; 625df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan switch (state) { 626df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_DESK: 627b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_LE_DESK: 628b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_HE_DESK: 629df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan numOfProfiles = 1; 630df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 631df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_CAR: 632df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan numOfProfiles = 2; 633df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 634df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan default: 635df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return null; 636df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 637df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 638436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfiles = new LocalBluetoothProfile[numOfProfiles]; 639df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mCheckedItems = new boolean[numOfProfiles]; 640df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan CharSequence[] items = new CharSequence[numOfProfiles]; 641df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 642436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // FIXME: convert switch to something else 643df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan switch (state) { 644df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_CAR: 645436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby items[0] = getString(R.string.bluetooth_dock_settings_headset); 646436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby items[1] = getString(R.string.bluetooth_dock_settings_a2dp); 647436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfiles[0] = mProfileManager.getHeadsetProfile(); 648436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfiles[1] = mProfileManager.getA2dpProfile(); 649df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (firstTime) { 650c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan // Enable by default for car dock 651c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan mCheckedItems[0] = true; 652c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan mCheckedItems[1] = true; 653df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } else { 654436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCheckedItems[0] = mProfiles[0].isPreferred(device); 655436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCheckedItems[1] = mProfiles[1].isPreferred(device); 656df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 657c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan break; 658c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan 659df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan case Intent.EXTRA_DOCK_STATE_DESK: 660b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_LE_DESK: 661b8dd637887606242c5cbeaa2fa952946f9013d8fJeff Brown case Intent.EXTRA_DOCK_STATE_HE_DESK: 662436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby items[0] = getString(R.string.bluetooth_dock_settings_a2dp); 663436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfiles[0] = mProfileManager.getA2dpProfile(); 664df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (firstTime) { 665c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan // Disable by default for desk dock 666c5aa68f3f2201227e85e52ee33937e70e7741c3cMichael Chan mCheckedItems[0] = false; 667df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } else { 668436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mCheckedItems[0] = mProfiles[0].isPreferred(device); 669df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 670df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan break; 671df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 672df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan return items; 673df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 674df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 675436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // TODO: move to background thread to fix strict mode warnings 6763fe86a346cdcd41fd9498591571d8b512a130240Michael Chan private void handleBtStateChange(Intent intent, int startId) { 677845e740fc63657438b9085376c8e7d60d8334a72Michael Chan int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 6783fe86a346cdcd41fd9498591571d8b512a130240Michael Chan synchronized (this) { 6793fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if(DEBUG) Log.d(TAG, "BtState = " + btState + " mPendingDevice = " + mPendingDevice); 6803fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if (btState == BluetoothAdapter.STATE_ON) { 681436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby handleBluetoothStateOn(startId); 6823fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } else if (btState == BluetoothAdapter.STATE_TURNING_OFF) { 6833fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // Remove the flag to disable BT if someone is turning off bt. 6843fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // The rational is that: 6853fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // a) if BT is off at undock time, no work needs to be done 6863fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // b) if BT is on at undock time, the user wants it on. 687436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby getPrefs().edit().remove(KEY_DISABLE_BT_WHEN_UNDOCKED).apply(); 6883fe86a346cdcd41fd9498591571d8b512a130240Michael Chan DockEventReceiver.finishStartingService(this, startId); 6893fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } else if (btState == BluetoothAdapter.STATE_OFF) { 6903fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // Bluetooth was turning off as we were trying to turn it on. 6913fe86a346cdcd41fd9498591571d8b512a130240Michael Chan // Let's try again 6923fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if(DEBUG) Log.d(TAG, "Bluetooth = OFF mPendingDevice = " + mPendingDevice); 693c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan 694c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan if (mPendingTurnOffStartId != INVALID_STARTID) { 695c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan DockEventReceiver.finishStartingService(this, mPendingTurnOffStartId); 696436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby getPrefs().edit().remove(KEY_DISABLE_BT).apply(); 697c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan mPendingTurnOffStartId = INVALID_STARTID; 698c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan } 699c93b82496e18830b1f6b7d441bd29bb1787b9a66Michael Chan 7003fe86a346cdcd41fd9498591571d8b512a130240Michael Chan if (mPendingDevice != null) { 701436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.enable(); 7023fe86a346cdcd41fd9498591571d8b512a130240Michael Chan mPendingTurnOnStartId = startId; 7033fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } else { 7043fe86a346cdcd41fd9498591571d8b512a130240Michael Chan DockEventReceiver.finishStartingService(this, startId); 7053fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 706146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan } 707146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan } 708845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } 709845e740fc63657438b9085376c8e7d60d8334a72Michael Chan 710436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private void handleBluetoothStateOn(int startId) { 711436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mPendingDevice != null) { 712436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mPendingDevice.equals(mDevice)) { 713436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if(DEBUG) { 714436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "applying settings"); 715436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 716436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby applyBtSettings(mPendingDevice, mPendingStartId); 717436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if(DEBUG) { 718436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "mPendingDevice (" + mPendingDevice + ") != mDevice (" 719436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby + mDevice + ')'); 720436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 721436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 722436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPendingDevice = null; 723436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockEventReceiver.finishStartingService(this, mPendingStartId); 724436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else { 725436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby final SharedPreferences prefs = getPrefs(); 726436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 727436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "A DISABLE_BT_WHEN_UNDOCKED = " 728436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby + prefs.getBoolean(KEY_DISABLE_BT_WHEN_UNDOCKED, false)); 729436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 730436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Reconnect if docked and bluetooth was enabled by user. 731436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Intent i = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT)); 732436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (i != null) { 733436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE, 734436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Intent.EXTRA_DOCK_STATE_UNDOCKED); 735436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) { 736436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice device = i 737436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 738436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device != null) { 739436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby connectIfEnabled(device); 740436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 741436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else if (prefs.getBoolean(KEY_DISABLE_BT, false) 742436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby && mLocalAdapter.disable()) { 743436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPendingTurnOffStartId = startId; 744436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby prefs.edit().remove(KEY_DISABLE_BT).apply(); 745436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 746436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 747436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 748436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 749436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 750436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mPendingTurnOnStartId != INVALID_STARTID) { 751436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockEventReceiver.finishStartingService(this, mPendingTurnOnStartId); 752436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPendingTurnOnStartId = INVALID_STARTID; 753436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 754436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 755436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby DockEventReceiver.finishStartingService(this, startId); 756436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 757436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 758436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private synchronized void handleUnexpectedDisconnect(BluetoothDevice disconnectedDevice, 759436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfile profile, int startId) { 760436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 761436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "handling failed connect for " + disconnectedDevice); 762436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 763732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 764732c1dad5a4871597652f17986b7a602897e5a76Michael Chan // Reconnect if docked. 765732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (disconnectedDevice != null) { 766732c1dad5a4871597652f17986b7a602897e5a76Michael Chan // registerReceiver can't be called from a BroadcastReceiver 767436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Intent intent = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT)); 768436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (intent != null) { 769436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 770732c1dad5a4871597652f17986b7a602897e5a76Michael Chan Intent.EXTRA_DOCK_STATE_UNDOCKED); 771732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) { 772436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothDevice dockedDevice = intent 773732c1dad5a4871597652f17986b7a602897e5a76Michael Chan .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 774732c1dad5a4871597652f17986b7a602897e5a76Michael Chan if (dockedDevice != null && dockedDevice.equals(disconnectedDevice)) { 775436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice( 776436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby dockedDevice); 777436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice.connectProfile(profile); 778732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 779732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 780732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 781732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 782732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 783732c1dad5a4871597652f17986b7a602897e5a76Michael Chan DockEventReceiver.finishStartingService(this, startId); 784732c1dad5a4871597652f17986b7a602897e5a76Michael Chan } 785732c1dad5a4871597652f17986b7a602897e5a76Michael Chan 786845e740fc63657438b9085376c8e7d60d8334a72Michael Chan private synchronized void connectIfEnabled(BluetoothDevice device) { 787436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice( 788436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby device); 789436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<LocalBluetoothProfile> profiles = cachedDevice.getConnectableProfiles(); 790436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (LocalBluetoothProfile profile : profiles) { 791436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (profile.getPreferred(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) { 7924bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby cachedDevice.connect(false); 793436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 794845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } 795845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } 796845e740fc63657438b9085376c8e7d60d8334a72Michael Chan } 797146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 798436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private synchronized void applyBtSettings(BluetoothDevice device, int startId) { 799436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (device == null || mProfiles == null || mCheckedItems == null 800436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby || mLocalAdapter == null) { 801146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan return; 802436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 803146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 804146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan // Turn on BT if something is enabled 805436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby for (boolean enable : mCheckedItems) { 806436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (enable) { 807436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int btState = mLocalAdapter.getBluetoothState(); 808436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) { 809436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby Log.d(TAG, "BtState = " + btState); 810436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 811436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // May have race condition as the phone comes in and out and in the dock. 812436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Always turn on BT 813436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mLocalAdapter.enable(); 814436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 815436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // if adapter was previously OFF, TURNING_OFF, or TURNING_ON 816436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (btState != BluetoothAdapter.STATE_ON) { 817436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mPendingDevice != null && mPendingDevice.equals(mDevice)) { 818436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 819436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 820436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 821436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPendingDevice = device; 822436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mPendingStartId = startId; 823436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (btState != BluetoothAdapter.STATE_TURNING_ON) { 824436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby getPrefs().edit().putBoolean( 825436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby KEY_DISABLE_BT_WHEN_UNDOCKED, true).apply(); 826146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan } 827436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return; 828146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan } 829146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan } 830146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan } 831146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 832146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan mPendingDevice = null; 833146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan 834d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan boolean callConnect = false; 835436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice( 836d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan device); 837df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan for (int i = 0; i < mProfiles.length; i++) { 838436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby LocalBluetoothProfile profile = mProfiles[i]; 839436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (DEBUG) Log.d(TAG, profile.toString() + " = " + mCheckedItems[i]); 840df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 841fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan if (mCheckedItems[i]) { 842df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan // Checked but not connected 843d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan callConnect = true; 844fb5b54d77aee1b2d6a0c0ffe7d47c73a204dee28Michael Chan } else if (!mCheckedItems[i]) { 8459d03e98d22c51e81a01b2bdc91b825bd3b438481Jaikumar Ganesh // Unchecked, may or may not be connected. 846436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int status = profile.getConnectionStatus(cachedDevice.getDevice()); 847436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (status == BluetoothProfile.STATE_CONNECTED) { 8489d03e98d22c51e81a01b2bdc91b825bd3b438481Jaikumar Ganesh if (DEBUG) Log.d(TAG, "applyBtSettings - Disconnecting"); 8499d03e98d22c51e81a01b2bdc91b825bd3b438481Jaikumar Ganesh cachedDevice.disconnect(mProfiles[i]); 8509d03e98d22c51e81a01b2bdc91b825bd3b438481Jaikumar Ganesh } 851df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 852436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby profile.setPreferred(device, mCheckedItems[i]); 853df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (DEBUG) { 854436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mCheckedItems[i] != profile.isPreferred(device)) { 855e79f990490de49b39097433707c2bae6d8238330Jake Hamby Log.e(TAG, "Can't save preferred value"); 856df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 857df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 858df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 859d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan 860d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan if (callConnect) { 861d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan if (DEBUG) Log.d(TAG, "applyBtSettings - Connecting"); 8624bd7cb0e07a1fbc4e658810631132cebd5b1fdd6Jake Hamby cachedDevice.connect(false); 863d8eec52a3786a51b38ed280afd84005e6da05ce6Michael Chan } 864df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 865df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 866436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private synchronized void handleDocked(BluetoothDevice device, int state, 867436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby int startId) { 868f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device != null && 869f892bc856c6780187db62681d59ca538a173590fEric Laurent LocalBluetoothPreferences.getDockAutoConnectSetting(this, device.getAddress())) { 87057d5585595810044e7727d4303214f69ff2d77d4Michael Chan // Setting == auto connect 871436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby initBtSettings(device, state, false); 87257d5585595810044e7727d4303214f69ff2d77d4Michael Chan applyBtSettings(mDevice, startId); 87357d5585595810044e7727d4303214f69ff2d77d4Michael Chan } else { 874436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby createDialog(device, state, startId); 87557d5585595810044e7727d4303214f69ff2d77d4Michael Chan } 87657d5585595810044e7727d4303214f69ff2d77d4Michael Chan } 87757d5585595810044e7727d4303214f69ff2d77d4Michael Chan 878436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private synchronized void handleUndocked(BluetoothDevice device) { 87957d5585595810044e7727d4303214f69ff2d77d4Michael Chan mRunnable = null; 880436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager.removeServiceListener(this); 881df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan if (mDialog != null) { 882df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDialog.dismiss(); 883df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDialog = null; 884df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 885df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan mDevice = null; 886146385663bb55d9f55ad179d3c35ccf5cac13fc8Michael Chan mPendingDevice = null; 887f892bc856c6780187db62681d59ca538a173590fEric Laurent if (device != null) { 888f892bc856c6780187db62681d59ca538a173590fEric Laurent CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(device); 889f892bc856c6780187db62681d59ca538a173590fEric Laurent cachedDevice.disconnect(); 890f892bc856c6780187db62681d59ca538a173590fEric Laurent } 891df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 892df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan 893436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private CachedBluetoothDevice getCachedBluetoothDevice(BluetoothDevice device) { 894436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); 895436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (cachedDevice == null) { 896436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device); 897df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan } 898436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return cachedDevice; 8993fe86a346cdcd41fd9498591571d8b512a130240Michael Chan } 90057d5585595810044e7727d4303214f69ff2d77d4Michael Chan 90157d5585595810044e7727d4303214f69ff2d77d4Michael Chan public synchronized void onServiceConnected() { 90257d5585595810044e7727d4303214f69ff2d77d4Michael Chan if (mRunnable != null) { 90357d5585595810044e7727d4303214f69ff2d77d4Michael Chan mRunnable.run(); 90457d5585595810044e7727d4303214f69ff2d77d4Michael Chan mRunnable = null; 905436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mProfileManager.removeServiceListener(this); 90657d5585595810044e7727d4303214f69ff2d77d4Michael Chan } 90757d5585595810044e7727d4303214f69ff2d77d4Michael Chan } 90857d5585595810044e7727d4303214f69ff2d77d4Michael Chan 90957d5585595810044e7727d4303214f69ff2d77d4Michael Chan public void onServiceDisconnected() { 910436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // FIXME: shouldn't I do something on service disconnected too? 91157d5585595810044e7727d4303214f69ff2d77d4Michael Chan } 912df9504ef58e8dafdd80ca9cd780510f9444943e2Michael Chan} 913