186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal/*
286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * Copyright (C) 2017 The Android Open Source Project
386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal *
486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * Licensed under the Apache License, Version 2.0 (the "License");
586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * you may not use this file except in compliance with the License.
686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * You may obtain a copy of the License at
786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal *
886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal *      http://www.apache.org/licenses/LICENSE-2.0
986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal *
1086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * Unless required by applicable law or agreed to in writing, software
1186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * distributed under the License is distributed on an "AS IS" BASIS,
1286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * See the License for the specific language governing permissions and
1486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal * limitations under the License.
1586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal */
1686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
1786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalpackage com.android.bluetooth.btservice;
1886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
1986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothA2dp;
2086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothAdapter;
2186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothDevice;
2286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothHeadset;
2386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothProfile;
2486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothSap;
2586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.BluetoothUuid;
2686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.bluetooth.IBluetooth;
2786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.content.BroadcastReceiver;
2886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.content.Context;
2986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.content.Intent;
3086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.content.IntentFilter;
3186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.os.Handler;
3286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.os.Looper;
3386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.os.Message;
3486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.os.Parcelable;
3586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.os.ParcelUuid;
3686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport android.util.Log;
3786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
3886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport com.android.bluetooth.a2dp.A2dpService;
3986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport com.android.bluetooth.hid.HidService;
4086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport com.android.bluetooth.hfp.HeadsetService;
4186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport com.android.bluetooth.pan.PanService;
4286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport com.android.internal.R;
4386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
44ff5b7361a8db715a092bf93346408d342ebd354aJack Heimport java.util.HashSet;
4586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalimport java.util.List;
4686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
4786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// Describes the phone policy
4886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal//
4986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// The policy should be as decoupled from the stack as possible. In an ideal world we should not
5086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// need to have this policy talk with any non-public APIs and one way to enforce that would be to
5186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// keep this file outside the Bluetooth process. Unfortunately, keeping a separate process alive is
5286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// an expensive and a tedious task.
5386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal//
5486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// Best practices:
5586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// a) PhonePolicy should be ALL private methods
5686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal//    -- Use broadcasts which can be listened in on the BroadcastReceiver
5786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// b) NEVER call from the PhonePolicy into the Java stack, unless public APIs. It is OK to call into
5886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// the non public versions as long as public versions exist (so that a 3rd party policy can mimick)
5986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// us.
6086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal//
6186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// Policy description:
6286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal//
6386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// Policies are usually governed by outside events that may warrant an action. We talk about various
6486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// events and the resulting outcome from this policy:
6586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal//
6686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// 1. Adapter turned ON: At this point we will try to auto-connect the (device, profile) pairs which
6786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// have PRIORITY_AUTO_CONNECT. The fact that we *only* auto-connect Headset and A2DP is something
6886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// that is hardcoded and specific to phone policy (see autoConnect() function)
6986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// 2. When the profile connection-state changes: At this point if a new profile gets CONNECTED we
7086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// will try to connect other profiles on the same device. This is to avoid collision if devices
7186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal// somehow end up trying to connect at same time or general connection issues.
7286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwalclass PhonePolicy {
7386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static boolean DBG = true;
7486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static String TAG = "BluetoothPhonePolicy";
7586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
7686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // Message types for the handler (internal messages generated by intents or timeouts)
7786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED = 1;
7886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static int MESSAGE_PROFILE_INIT_PRIORITIES = 2;
7986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static int MESSAGE_CONNECT_OTHER_PROFILES = 3;
8086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static int MESSAGE_ADAPTER_STATE_TURNED_ON = 4;
8186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
8286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // Timeouts
8386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private static int CONNECT_OTHER_PROFILES_TIMEOUT = 6000; // 6s
8486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
8586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private AdapterService mAdapterService;
8686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private ServiceFactory mFactory;
8786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    final private Handler mHandler;
88ff5b7361a8db715a092bf93346408d342ebd354aJack He    final private HashSet<BluetoothDevice> mHeadsetRetrySet = new HashSet<>();
89ff5b7361a8db715a092bf93346408d342ebd354aJack He    final private HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>();
9086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
9186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // Broadcast receiver for all changes to states of various profiles
9286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
9386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        @Override
9486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        public void onReceive(Context context, Intent intent) {
95b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            String action = intent.getAction();
96b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            if (action == null) {
97b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                errorLog("Received intent with null action");
98b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                return;
99b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            }
100b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            switch (action) {
101b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
102b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
103b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                                    BluetoothProfile.HEADSET,
104b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                                    -1, // No-op argument
105b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                                    intent)
106b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                            .sendToTarget();
107b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    break;
108b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
109b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
110b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                                    BluetoothProfile.A2DP,
111b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                                    -1, // No-op argument
112b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                                    intent)
113b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                            .sendToTarget();
114b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    break;
115b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                case BluetoothAdapter.ACTION_STATE_CHANGED:
116b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    // Only pass the message on if the adapter has actually changed state from
117b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    // non-ON to ON. NOTE: ON is the state depicting BREDR ON and not just BLE ON.
118b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
119b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    if (newState == BluetoothAdapter.STATE_ON) {
120b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                        mHandler.obtainMessage(MESSAGE_ADAPTER_STATE_TURNED_ON).sendToTarget();
121b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    }
122b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    break;
123b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                case BluetoothDevice.ACTION_UUID:
124b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES, intent).sendToTarget();
125b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    break;
126b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                default:
127b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    Log.e(TAG, "Received unexpected intent, action=" + action);
128b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    break;
12986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
13086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
13186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    };
13286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
13386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // ONLY for testing
13486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    public BroadcastReceiver getBroadcastReceiver() {
13586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        return mReceiver;
13686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
13786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
13886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // Handler to handoff intents to class thread
13986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    class PhonePolicyHandler extends Handler {
14086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        PhonePolicyHandler(Looper looper) {
14186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            super(looper);
14286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
14386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
14486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        @Override
14586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        public void handleMessage(Message msg) {
14686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            switch (msg.what) {
14786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                case MESSAGE_PROFILE_INIT_PRIORITIES: {
148b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    Intent intent = (Intent) msg.obj;
14986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    BluetoothDevice device =
150b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
151b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
152b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                    debugLog("Received ACTION_UUID for device " + device);
1530068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                    if (uuids != null) {
1540068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                        ParcelUuid[] uuidsToSend = new ParcelUuid[uuids.length];
1550068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                        for (int i = 0; i < uuidsToSend.length; i++) {
1560068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                            uuidsToSend[i] = (ParcelUuid) uuids[i];
157b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                            debugLog("index=" + i + "uuid=" + uuidsToSend[i]);
1580068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                        }
1590068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                        processInitProfilePriorities(device, uuidsToSend);
1600068bdad22ffd70c90de67b6e85c8a0dfa838d90Sanket Agarwal                    }
16186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                } break;
16286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
16386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: {
16486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    Intent intent = (Intent) msg.obj;
16586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    BluetoothDevice device =
16686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
16786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    int prevState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
16886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    int nextState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
16986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    processProfileStateChanged(device, msg.arg1, nextState, prevState);
17086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                } break;
17186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
17286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                case MESSAGE_CONNECT_OTHER_PROFILES:
17386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    // Called when we try connect some profiles in processConnectOtherProfiles but
17486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    // we send a delayed message to try connecting the remaining profiles
17586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    processConnectOtherProfiles((BluetoothDevice) msg.obj);
17686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    break;
17786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
17886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                case MESSAGE_ADAPTER_STATE_TURNED_ON:
17986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    // Call auto connect when adapter switches state to ON
180ff5b7361a8db715a092bf93346408d342ebd354aJack He                    resetStates();
18186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    autoConnect();
18286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    break;
18386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
18486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
18586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    };
18686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
18786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // Policy API functions for lifecycle management (protected)
18886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    protected void start() {
18986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        IntentFilter filter = new IntentFilter();
19086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
19186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
19286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        filter.addAction(BluetoothDevice.ACTION_UUID);
19386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
19486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        mAdapterService.registerReceiver(mReceiver, filter);
19586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
19686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    protected void cleanup() {
19786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        mAdapterService.unregisterReceiver(mReceiver);
198ff5b7361a8db715a092bf93346408d342ebd354aJack He        resetStates();
19986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
20086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
20186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    PhonePolicy(AdapterService service, ServiceFactory factory) {
20286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        mAdapterService = service;
20386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        mFactory = factory;
20486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        mHandler = new PhonePolicyHandler(service.getMainLooper());
20586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
20686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
20786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // Policy implementation, all functions MUST be private
20886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void processInitProfilePriorities(BluetoothDevice device, ParcelUuid[] uuids) {
209b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        debugLog("processInitProfilePriorities() - device " + device);
21086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        HidService hidService = mFactory.getHidService();
21186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        A2dpService a2dpService = mFactory.getA2dpService();
21286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        HeadsetService headsetService = mFactory.getHeadsetService();
21386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        PanService panService = mFactory.getPanService();
21486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
21586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        // Set profile priorities only for the profiles discovered on the remote device.
21686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        // This avoids needless auto-connect attempts to profiles non-existent on the remote device
21786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if ((hidService != null)
21886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid)
21986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                           || BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp))
22086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)) {
22186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            hidService.setPriority(device, BluetoothProfile.PRIORITY_ON);
22286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
22386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
22486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        // If we do not have a stored priority for HFP/A2DP (all roles) then default to on.
22586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if ((headsetService != null)
22686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)
22786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                            || BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))
22886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                           && (headsetService.getPriority(device)
22986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                                      == BluetoothProfile.PRIORITY_UNDEFINED))) {
23086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            headsetService.setPriority(device, BluetoothProfile.PRIORITY_ON);
23186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
23286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
23386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if ((a2dpService != null)
23486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)
23586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                           || BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AdvAudioDist))
23686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)) {
23786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
23886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
23986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
24086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if ((panService != null)
24186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.PANU)
24286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                           && (panService.getPriority(device)
24386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                                      == BluetoothProfile.PRIORITY_UNDEFINED)
24486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                           && mAdapterService.getResources().getBoolean(
24586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                                      R.bool.config_bluetooth_pan_enable_autoconnect))) {
24686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            panService.setPriority(device, BluetoothProfile.PRIORITY_ON);
24786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
24886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
24986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
25086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void processProfileStateChanged(
25186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            BluetoothDevice device, int profileId, int nextState, int prevState) {
252b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        debugLog("processProfileStateChanged, device=" + device + ", profile=" + profileId + ", "
253b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                + prevState + " -> " + nextState);
25486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET))
25586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                && (nextState == BluetoothProfile.STATE_CONNECTED)) {
256ff5b7361a8db715a092bf93346408d342ebd354aJack He            switch (profileId) {
257ff5b7361a8db715a092bf93346408d342ebd354aJack He                case BluetoothProfile.A2DP:
258ff5b7361a8db715a092bf93346408d342ebd354aJack He                    mA2dpRetrySet.remove(device);
259ff5b7361a8db715a092bf93346408d342ebd354aJack He                    break;
260ff5b7361a8db715a092bf93346408d342ebd354aJack He                case BluetoothProfile.HEADSET:
261ff5b7361a8db715a092bf93346408d342ebd354aJack He                    mHeadsetRetrySet.remove(device);
262ff5b7361a8db715a092bf93346408d342ebd354aJack He                    break;
263ff5b7361a8db715a092bf93346408d342ebd354aJack He            }
26486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            connectOtherProfile(device);
26586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            setProfileAutoConnectionPriority(device, profileId);
26686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
26786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
26886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
269ff5b7361a8db715a092bf93346408d342ebd354aJack He    private void resetStates() {
270ff5b7361a8db715a092bf93346408d342ebd354aJack He        mHeadsetRetrySet.clear();
271ff5b7361a8db715a092bf93346408d342ebd354aJack He        mA2dpRetrySet.clear();
272ff5b7361a8db715a092bf93346408d342ebd354aJack He    }
273ff5b7361a8db715a092bf93346408d342ebd354aJack He
27486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void autoConnect() {
27586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
27686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            errorLog("autoConnect() - BT is not ON. Exiting autoConnect");
27786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            return;
27886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
27986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
280b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        if (!mAdapterService.isQuietModeEnabled()) {
28186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            debugLog("autoConnect() - Initiate auto connection on BT on...");
28286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            // Phone profiles.
28386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            autoConnectHeadset();
28486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            autoConnectA2dp();
28586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        } else {
28686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            debugLog("autoConnect() - BT is in quiet mode. Not initiating auto connections");
28786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
28886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
28986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
29086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void autoConnectHeadset() {
291b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        final HeadsetService hsService = mFactory.getHeadsetService();
29286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (hsService == null) {
293b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            errorLog("autoConnectHeadset, service is null");
29486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            return;
29586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
296b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        final BluetoothDevice bondedDevices[] = mAdapterService.getBondedDevices();
29786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (bondedDevices == null) {
298b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            errorLog("autoConnectHeadset, bondedDevices are null");
29986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            return;
30086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
30186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        for (BluetoothDevice device : bondedDevices) {
302b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            debugLog("autoConnectHeadset, attempt auto-connect with device " + device);
30386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
304b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                debugLog("autoConnectHeadset, Connecting HFP with " + device);
30586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                hsService.connect(device);
30686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
30786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
30886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
30986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
31086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void autoConnectA2dp() {
311b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        final A2dpService a2dpService = mFactory.getA2dpService();
312b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        if (a2dpService == null) {
313b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            errorLog("autoConnectA2dp, service is null");
314b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            return;
315b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        }
316b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        final BluetoothDevice bondedDevices[] = mAdapterService.getBondedDevices();
317b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        if (bondedDevices == null) {
318b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            errorLog("autoConnectA2dp, bondedDevices are null");
31986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            return;
32086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
32186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        for (BluetoothDevice device : bondedDevices) {
322b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            debugLog("autoConnectA2dp, attempt auto-connect with device " + device);
323b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            if (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT) {
324b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                debugLog("autoConnectA2dp, connecting A2DP with " + device);
325b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                a2dpService.connect(device);
32686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
32786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
32886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
32986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
330b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    private void connectOtherProfile(BluetoothDevice device) {
331b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        if ((!mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES))
332b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                && (!mAdapterService.isQuietModeEnabled())) {
33386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES);
33486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            m.obj = device;
33586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            mHandler.sendMessageDelayed(m, CONNECT_OTHER_PROFILES_TIMEOUT);
33686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
33786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
33886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
33986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // This function is called whenever a profile is connected.  This allows any other bluetooth
34086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // profiles which are not already connected or in the process of connecting to attempt to
34186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // connect to the device that initiated the connection.  In the event that this function is
34286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    // invoked and there are no current bluetooth connections no new profiles will be connected.
34386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void processConnectOtherProfiles(BluetoothDevice device) {
344b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        debugLog("processConnectOtherProfiles, device=" + device);
34586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
346b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            warnLog("processConnectOtherProfiles, adapter is not ON " + mAdapterService.getState());
34786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            return;
34886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
34986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        HeadsetService hsService = mFactory.getHeadsetService();
35086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        A2dpService a2dpService = mFactory.getA2dpService();
35186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        PanService panService = mFactory.getPanService();
35286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
35386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        boolean allProfilesEmpty = true;
35486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        List<BluetoothDevice> a2dpConnDevList = null;
35586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        List<BluetoothDevice> hsConnDevList = null;
35686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        List<BluetoothDevice> panConnDevList = null;
35786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
35886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (hsService != null) {
35986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            hsConnDevList = hsService.getConnectedDevices();
36086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            allProfilesEmpty = allProfilesEmpty && hsConnDevList.isEmpty();
36186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
36286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (a2dpService != null) {
36386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            a2dpConnDevList = a2dpService.getConnectedDevices();
36486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            allProfilesEmpty = allProfilesEmpty && a2dpConnDevList.isEmpty();
36586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
36686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (panService != null) {
36786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            panConnDevList = panService.getConnectedDevices();
36886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            allProfilesEmpty = allProfilesEmpty && panConnDevList.isEmpty();
36986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
37086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
37186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (allProfilesEmpty) {
372ff5b7361a8db715a092bf93346408d342ebd354aJack He            // considered as fully disconnected, don't bother connecting others.
373b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He            debugLog("processConnectOtherProfiles, all profiles disconnected for " + device);
374ff5b7361a8db715a092bf93346408d342ebd354aJack He            // reset retry status so that in the next round we can start retrying connections again
375ff5b7361a8db715a092bf93346408d342ebd354aJack He            resetStates();
37686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            return;
37786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
37886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
37986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (hsService != null) {
380ff5b7361a8db715a092bf93346408d342ebd354aJack He            if (hsConnDevList.isEmpty() && !mHeadsetRetrySet.contains(device)
38186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
38286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && (hsService.getConnectionState(device)
38386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                               == BluetoothProfile.STATE_DISCONNECTED)) {
384b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                debugLog("Retrying connection to Headset with device " + device);
385ff5b7361a8db715a092bf93346408d342ebd354aJack He                mHeadsetRetrySet.add(device);
38686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                hsService.connect(device);
38786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
38886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
38986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (a2dpService != null) {
390ff5b7361a8db715a092bf93346408d342ebd354aJack He            if (a2dpConnDevList.isEmpty() && !mA2dpRetrySet.contains(device)
39186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
39286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && (a2dpService.getConnectionState(device)
39386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                               == BluetoothProfile.STATE_DISCONNECTED)) {
39486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                debugLog("Retrying connection to A2DP with device " + device);
395ff5b7361a8db715a092bf93346408d342ebd354aJack He                mA2dpRetrySet.add(device);
39686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                a2dpService.connect(device);
39786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
39886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
39986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        if (panService != null) {
40086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            if (panConnDevList.isEmpty()
40186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && (panService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)
40286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && (panService.getConnectionState(device)
40386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                               == BluetoothProfile.STATE_DISCONNECTED)) {
404b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                debugLog("Retrying connection to PAN with device " + device);
40586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                panService.connect(device);
40686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
40786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
40886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
40986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
410b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId) {
41186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        switch (profileId) {
41286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            case BluetoothProfile.HEADSET:
41386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                HeadsetService hsService = mFactory.getHeadsetService();
414b8f2c708191ab9b31eaff709d4767f3e4fa03164xutianguo                if ((hsService != null)
415b8f2c708191ab9b31eaff709d4767f3e4fa03164xutianguo                        && (BluetoothProfile.PRIORITY_AUTO_CONNECT
416b8f2c708191ab9b31eaff709d4767f3e4fa03164xutianguo                                   != hsService.getPriority(device))) {
417b8f2c708191ab9b31eaff709d4767f3e4fa03164xutianguo                    List<BluetoothDevice> deviceList = hsService.getConnectedDevices();
41886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    adjustOtherHeadsetPriorities(hsService, deviceList);
41986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    hsService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT);
42086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                }
42186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                break;
42286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
42386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            case BluetoothProfile.A2DP:
42486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                A2dpService a2dpService = mFactory.getA2dpService();
42586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                if ((a2dpService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT
42686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                                                     != a2dpService.getPriority(device))) {
42786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    adjustOtherSinkPriorities(a2dpService, device);
42886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    a2dpService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT);
42986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                }
43086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                break;
43186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
43286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            default:
433b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He                Log.w(TAG, "Tried to set AutoConnect priority on invalid profile " + profileId);
43486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                break;
43586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
43686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
43786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
43886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void adjustOtherHeadsetPriorities(
43986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            HeadsetService hsService, List<BluetoothDevice> connectedDeviceList) {
44086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        for (BluetoothDevice device : mAdapterService.getBondedDevices()) {
44186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT
44286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && !connectedDeviceList.contains(device)) {
44386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                hsService.setPriority(device, BluetoothProfile.PRIORITY_ON);
44486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
44586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
44686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
44786c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal
44886c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    private void adjustOtherSinkPriorities(
44986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            A2dpService a2dpService, BluetoothDevice connectedDevice) {
45086c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        for (BluetoothDevice device : mAdapterService.getBondedDevices()) {
45186c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT
45286c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                    && !device.equals(connectedDevice)) {
45386c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal                a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON);
45486c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal            }
45586c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal        }
45686c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal    }
457b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He
458b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    private static void debugLog(String msg) {
459b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        if (DBG) Log.d(TAG, msg);
460b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    }
461b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He
462b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    private static void warnLog(String msg) {
463b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        Log.w(TAG, msg);
464b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    }
465b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He
466b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    private static void errorLog(String msg) {
467b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He        Log.e(TAG, msg);
468b7cafbaa7a50e61c5e473a874c14ea050f5c38abJack He    }
46986c29fe88456bdcfbd4334647b04ef81ff384a06Sanket Agarwal}
470