1ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/*
2ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Copyright (C) 2012 The Android Open Source Project
3ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *
4ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License");
5ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * you may not use this file except in compliance with the License.
6ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * You may obtain a copy of the License at
7ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *
8ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *      http://www.apache.org/licenses/LICENSE-2.0
9ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu *
10ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Unless required by applicable law or agreed to in writing, software
11ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS,
12ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * See the License for the specific language governing permissions and
14ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * limitations under the License.
15ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
16ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
17ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshpackage com.android.bluetooth.btservice;
18ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
19ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.bluetooth.BluetoothAdapter;
204f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport android.bluetooth.BluetoothProfile;
21ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.bluetooth.BluetoothDevice;
224f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport com.android.bluetooth.a2dp.A2dpService;
234f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport com.android.bluetooth.hid.HidService;
244f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport com.android.bluetooth.hfp.HeadsetService;
25ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.content.Context;
26ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.content.Intent;
27ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.os.Message;
28bd704c741b8c523ad747214f6f0520ac3e2caf8fZhihai Xuimport android.os.UserHandle;
29ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.util.Log;
30ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
31ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.bluetooth.Utils;
32ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
33ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.internal.util.State;
34ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.internal.util.StateMachine;
35ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
36ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.util.ArrayList;
37ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
38ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/**
39ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * This state machine handles Bluetooth Adapter State.
40ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * States:
41ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link StableState} :  No device is in bonding / unbonding state.
42ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link PendingCommandState} : Some device is in bonding / unbonding state.
43ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * TODO(BT) This class can be removed and this logic moved to the stack.
44ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
45ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
46ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshfinal class BondStateMachine extends StateMachine {
47fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie    private static final boolean DBG = false;
48ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private static final String TAG = "BluetoothBondStateMachine";
49ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
50ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int CREATE_BOND = 1;
51ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int CANCEL_BOND = 2;
52ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int REMOVE_BOND = 3;
53ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int BONDING_STATE_CHANGE = 4;
54ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
55986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan    static final int BOND_STATE_NONE = 0;
56986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan    static final int BOND_STATE_BONDING = 1;
57986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan    static final int BOND_STATE_BONDED = 2;
58986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan
596654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterService mAdapterService;
606654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterProperties mAdapterProperties;
616654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private RemoteDevices mRemoteDevices;
62179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy    private BluetoothAdapter mAdapter;
63ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
64ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private PendingCommandState mPendingCommandState = new PendingCommandState();
65ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private StableState mStableState = new StableState();
66ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
676893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    private BondStateMachine(AdapterService service,
6831ba132491053bc86d419a7d51fc04af3299c076fredc            AdapterProperties prop, RemoteDevices remoteDevices) {
69ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        super("BondStateMachine:");
70ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mStableState);
71ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mPendingCommandState);
7231ba132491053bc86d419a7d51fc04af3299c076fredc        mRemoteDevices = remoteDevices;
73ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterService = service;
74ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterProperties = prop;
75179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        mAdapter = BluetoothAdapter.getDefaultAdapter();
766654f5c903de510a70f9e72cd5ad7837b615d93ffredc        setInitialState(mStableState);
776654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
786654f5c903de510a70f9e72cd5ad7837b615d93ffredc
796893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    public static BondStateMachine make(AdapterService service,
806893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville            AdapterProperties prop, RemoteDevices remoteDevices) {
816893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        Log.d(TAG, "make");
826893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        BondStateMachine bsm = new BondStateMachine(service, prop, remoteDevices);
836893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        bsm.start();
846893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        return bsm;
856893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    }
866893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville
8715d36984a79d6e35c659edb0efdf929f0b526bd5Fred    public void doQuit() {
8815d36984a79d6e35c659edb0efdf929f0b526bd5Fred        quitNow();
8915d36984a79d6e35c659edb0efdf929f0b526bd5Fred    }
9015d36984a79d6e35c659edb0efdf929f0b526bd5Fred
916654f5c903de510a70f9e72cd5ad7837b615d93ffredc    public void cleanup() {
9274ae04c73312403e89db0f8e9bd9601d403b4783fredc        mAdapterService = null;
9374ae04c73312403e89db0f8e9bd9601d403b4783fredc        mRemoteDevices = null;
9474ae04c73312403e89db0f8e9bd9601d403b4783fredc        mAdapterProperties = null;
95ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
96ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
97ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class StableState extends State {
98ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
99ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
1007aab11364743cbca6eeefecbbde19f0434aff362fredc            infoLog("StableState(): Entering Off State");
101ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
102ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
103ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
104ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
105b5cc776c9353a203cdde97e62b25f05d9633d14cfredc
106ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            BluetoothDevice dev = (BluetoothDevice)msg.obj;
1076654f5c903de510a70f9e72cd5ad7837b615d93ffredc
108ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch(msg.what) {
1096654f5c903de510a70f9e72cd5ad7837b615d93ffredc
110ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              case CREATE_BOND:
111ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  createBond(dev, true);
112ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  break;
113ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              case REMOVE_BOND:
114ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  removeBond(dev, true);
115ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  break;
116ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              case BONDING_STATE_CHANGE:
117986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                int newState = msg.arg1;
118986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                /* if incoming pairing, transition to pending state */
119986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                if (newState == BluetoothDevice.BOND_BONDING)
120986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                {
121ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                    sendIntent(dev, newState, 0);
122986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                    transitionTo(mPendingCommandState);
123986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                }
124986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                else
125986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                {
126986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                    Log.e(TAG, "In stable state, received invalid newState: " + newState);
127986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                }
128986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                break;
129986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan
130986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan              case CANCEL_BOND:
131ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              default:
132ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   Log.e(TAG, "Received unhandled state: " + msg.what);
133ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   return false;
134ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
135ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
136ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
138ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
139ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
140ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class PendingCommandState extends State {
141ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        private final ArrayList<BluetoothDevice> mDevices =
142ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            new ArrayList<BluetoothDevice>();
143ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
144ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
145ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
146ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            infoLog("Entering PendingCommandState State");
147ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            BluetoothDevice dev = (BluetoothDevice)getCurrentMessage().obj;
148ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
149ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
150ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
151ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
1527aab11364743cbca6eeefecbbde19f0434aff362fredc
153ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            BluetoothDevice dev = (BluetoothDevice)msg.obj;
154aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera            boolean result = false;
155ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (mDevices.contains(dev) &&
156ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    msg.what != CANCEL_BOND && msg.what != BONDING_STATE_CHANGE) {
157ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                deferMessage(msg);
158ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return true;
159ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
160ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
161ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch (msg.what) {
162ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case CREATE_BOND:
163ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    result = createBond(dev, false);
164ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
165ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case REMOVE_BOND:
166ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    result = removeBond(dev, false);
167ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
168ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case CANCEL_BOND:
169ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    result = cancelBond(dev);
170ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
171ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case BONDING_STATE_CHANGE:
172ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    int newState = msg.arg1;
173ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                    int reason = getUnbondReasonFromHALCode(msg.arg2);
174ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                    sendIntent(dev, newState, reason);
175aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera                    if(newState != BluetoothDevice.BOND_BONDING )
176986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                    {
177986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        /* this is either none/bonded, remove and transition */
178986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        result = !mDevices.remove(dev);
179986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        if (mDevices.isEmpty()) {
180c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // Whenever mDevices is empty, then we need to
181c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // set result=false. Else, we will end up adding
182c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // the device to the list again. This prevents us
183c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // from pairing with a device that we just unpaired
184c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            result = false;
185986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                            transitionTo(mStableState);
186986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        }
1874f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        if (newState == BluetoothDevice.BOND_NONE)
1884f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        {
1894f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                            // Set the profile Priorities to undefined
1904f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                            clearProfilePriorty(dev);
1914f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        }
1924f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        else if (newState == BluetoothDevice.BOND_BONDED)
1934f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        {
1944f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                           // Restore the profile priorty settings
1954f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                           setProfilePriorty(dev);
1964f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        }
197ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    }
198aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera                    else if(!mDevices.contains(dev))
199aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera                        result=true;
200ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
201ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                default:
202ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    Log.e(TAG, "Received unhandled event:" + msg.what);
203ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    return false;
204ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
205ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (result) mDevices.add(dev);
206ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
207ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
208ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
209ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
210ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
211ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private boolean cancelBond(BluetoothDevice dev) {
212ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (dev.getBondState() == BluetoothDevice.BOND_BONDING) {
213ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
214ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (!mAdapterService.cancelBondNative(addr)) {
215ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               Log.e(TAG, "Unexpected error while cancelling bond:");
216ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else {
217ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return true;
218ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
219ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
220ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return false;
221ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
222ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
223ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private boolean removeBond(BluetoothDevice dev, boolean transition) {
224ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (dev.getBondState() == BluetoothDevice.BOND_BONDED) {
225ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
226ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (!mAdapterService.removeBondNative(addr)) {
227ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               Log.e(TAG, "Unexpected error while removing bond:");
228ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else {
229ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                if (transition) transitionTo(mPendingCommandState);
230ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return true;
231ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
232ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
233ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
234ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return false;
235ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
236ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
237ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private boolean createBond(BluetoothDevice dev, boolean transition) {
238ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
239ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            infoLog("Bond address is:" + dev);
240ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
241ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (!mAdapterService.createBondNative(addr)) {
242ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                sendIntent(dev, BluetoothDevice.BOND_NONE,
243ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                           BluetoothDevice.UNBOND_REASON_REMOVED);
244986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                return false;
245ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else if (transition) {
246ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                transitionTo(mPendingCommandState);
247ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
248ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
249ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
250ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return false;
251ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
252ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
253ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan    private void sendIntent(BluetoothDevice device, int newState, int reason) {
254ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        DeviceProperties devProp = mRemoteDevices.getDeviceProperties(device);
255179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        int oldState = BluetoothDevice.BOND_NONE;
256179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        if (devProp != null) {
257179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            oldState = devProp.getBondState();
258179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        }
259ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (oldState == newState) return;
260179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        mAdapterProperties.onBondStateChanged(device, newState);
2612f9a79b2d545e1a8b50a0018456892a9934db99aRavi Nagarajan
262ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
263ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
264ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, newState);
265ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
266ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        if (newState == BluetoothDevice.BOND_NONE)
267ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            intent.putExtra(BluetoothDevice.EXTRA_REASON, reason);
268bd704c741b8c523ad747214f6f0520ac3e2caf8fZhihai Xu        mAdapterService.sendBroadcastAsUser(intent, UserHandle.ALL,
269bd704c741b8c523ad747214f6f0520ac3e2caf8fZhihai Xu                AdapterService.BLUETOOTH_PERM);
270ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        infoLog("Bond State Change Intent:" + device + " OldState: " + oldState
271ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                + " NewState: " + newState);
272ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
273ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
274ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    void bondStateChangeCallback(int status, byte[] address, int newState) {
275ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        BluetoothDevice device = mRemoteDevices.getDevice(address);
276ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
277ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (device == null) {
278179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            infoLog("No record of the device:" + device);
279179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            // This device will be added as part of the BONDING_STATE_CHANGE intent processing
280179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            // in sendIntent above
281179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            device = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
282ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
283ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
284ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        infoLog("bondStateChangeCallback: Status: " + status + " Address: " + device
285ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                + " newState: " + newState);
286ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
287ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Message msg = obtainMessage(BONDING_STATE_CHANGE);
288ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        msg.obj = device;
289ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
290986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan        if (newState == BOND_STATE_BONDED)
291986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan            msg.arg1 = BluetoothDevice.BOND_BONDED;
292986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan        else if (newState == BOND_STATE_BONDING)
293986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan            msg.arg1 = BluetoothDevice.BOND_BONDING;
294986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan        else
295986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan            msg.arg1 = BluetoothDevice.BOND_NONE;
296ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        msg.arg2 = status;
297986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan
298ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        sendMessage(msg);
299ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
300ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
3014f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    private void setProfilePriorty (BluetoothDevice device){
3024f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HidService hidService = HidService.getHidService();
3034f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        A2dpService a2dpService = A2dpService.getA2dpService();
3044f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HeadsetService headsetService = HeadsetService.getHeadsetService();
3054f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3064f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if ((hidService != null) &&
3074f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
3084f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            hidService.setPriority(device,BluetoothProfile.PRIORITY_ON);
3094f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
3104f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3114f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if ((a2dpService != null) &&
3124f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
3134f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            a2dpService.setPriority(device,BluetoothProfile.PRIORITY_ON);
3144f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
3154f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3164f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if ((headsetService != null) &&
3174f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            (headsetService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
3184f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            headsetService.setPriority(device,BluetoothProfile.PRIORITY_ON);
3194f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
3204f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
3214f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3224f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    private void clearProfilePriorty (BluetoothDevice device){
3234f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HidService hidService = HidService.getHidService();
3244f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        A2dpService a2dpService = A2dpService.getA2dpService();
3254f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HeadsetService headsetService = HeadsetService.getHeadsetService();
3264f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3274f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if (hidService != null)
3284f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            hidService.setPriority(device,BluetoothProfile.PRIORITY_UNDEFINED);
3294f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if(a2dpService != null)
3304f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            a2dpService.setPriority(device,BluetoothProfile.PRIORITY_UNDEFINED);
3314f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if(headsetService != null)
3324f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            headsetService.setPriority(device,BluetoothProfile.PRIORITY_UNDEFINED);
3334f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
3344f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
335ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void infoLog(String msg) {
336ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Log.i(TAG, msg);
337ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
338ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
339ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void errorLog(String msg) {
340ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Log.e(TAG, msg);
341ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
34215d36984a79d6e35c659edb0efdf929f0b526bd5Fred
343ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan    private int getUnbondReasonFromHALCode (int reason) {
344ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        if (reason == AbstractionLayer.BT_STATUS_SUCCESS)
345ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            return BluetoothDevice.BOND_SUCCESS;
346ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        else if (reason == AbstractionLayer.BT_STATUS_RMT_DEV_DOWN)
347ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            return BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN;
348ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        else if (reason == AbstractionLayer.BT_STATUS_AUTH_FAILURE)
349ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            return BluetoothDevice.UNBOND_REASON_AUTH_FAILED;
35003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        else if (reason == AbstractionLayer.BT_STATUS_AUTH_REJECTED)
35103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            return BluetoothDevice.UNBOND_REASON_AUTH_REJECTED;
35203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        else if (reason == AbstractionLayer.BT_STATUS_AUTH_TIMEOUT)
35303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            return BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT;
354ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan
355ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        /* default */
356ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        return BluetoothDevice.UNBOND_REASON_REMOVED;
357ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan    }
358ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
359