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