BondStateMachine.java revision bd704c741b8c523ad747214f6f0520ac3e2caf8f
1ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/*
2ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * Copyright (C) 2012 Google Inc.
3ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
4ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
5ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshpackage com.android.bluetooth.btservice;
6ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
7ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.bluetooth.BluetoothAdapter;
84f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport android.bluetooth.BluetoothProfile;
9ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.bluetooth.BluetoothDevice;
104f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport com.android.bluetooth.a2dp.A2dpService;
114f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport com.android.bluetooth.hid.HidService;
124f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Battaimport com.android.bluetooth.hfp.HeadsetService;
13ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.content.Context;
14ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.content.Intent;
15ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.os.Message;
16bd704c741b8c523ad747214f6f0520ac3e2caf8fZhihai Xuimport android.os.UserHandle;
17ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.util.Log;
18ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
19ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.bluetooth.Utils;
20ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
21ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.internal.util.State;
22ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.internal.util.StateMachine;
23ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
24ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport java.util.ArrayList;
25ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
26ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/**
27ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * This state machine handles Bluetooth Adapter State.
28ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * States:
29ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link StableState} :  No device is in bonding / unbonding state.
30ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link PendingCommandState} : Some device is in bonding / unbonding state.
31ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * TODO(BT) This class can be removed and this logic moved to the stack.
32ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
33ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
34ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshfinal class BondStateMachine extends StateMachine {
35fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie    private static final boolean DBG = false;
36ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private static final String TAG = "BluetoothBondStateMachine";
37ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
38ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int CREATE_BOND = 1;
39ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int CANCEL_BOND = 2;
40ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int REMOVE_BOND = 3;
41ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int BONDING_STATE_CHANGE = 4;
42ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
43986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan    static final int BOND_STATE_NONE = 0;
44986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan    static final int BOND_STATE_BONDING = 1;
45986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan    static final int BOND_STATE_BONDED = 2;
46986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan
476654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterService mAdapterService;
486654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterProperties mAdapterProperties;
496654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private RemoteDevices mRemoteDevices;
50179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy    private BluetoothAdapter mAdapter;
51ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
52ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private PendingCommandState mPendingCommandState = new PendingCommandState();
53ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private StableState mStableState = new StableState();
54ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
556893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    private BondStateMachine(AdapterService service,
5631ba132491053bc86d419a7d51fc04af3299c076fredc            AdapterProperties prop, RemoteDevices remoteDevices) {
57ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        super("BondStateMachine:");
58ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mStableState);
59ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mPendingCommandState);
6031ba132491053bc86d419a7d51fc04af3299c076fredc        mRemoteDevices = remoteDevices;
61ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterService = service;
62ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterProperties = prop;
63179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        mAdapter = BluetoothAdapter.getDefaultAdapter();
646654f5c903de510a70f9e72cd5ad7837b615d93ffredc        setInitialState(mStableState);
656654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
666654f5c903de510a70f9e72cd5ad7837b615d93ffredc
676893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    public static BondStateMachine make(AdapterService service,
686893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville            AdapterProperties prop, RemoteDevices remoteDevices) {
696893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        Log.d(TAG, "make");
706893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        BondStateMachine bsm = new BondStateMachine(service, prop, remoteDevices);
716893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        bsm.start();
726893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        return bsm;
736893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    }
746893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville
7515d36984a79d6e35c659edb0efdf929f0b526bd5Fred    public void doQuit() {
7615d36984a79d6e35c659edb0efdf929f0b526bd5Fred        quitNow();
7715d36984a79d6e35c659edb0efdf929f0b526bd5Fred    }
7815d36984a79d6e35c659edb0efdf929f0b526bd5Fred
796654f5c903de510a70f9e72cd5ad7837b615d93ffredc    public void cleanup() {
8074ae04c73312403e89db0f8e9bd9601d403b4783fredc        mAdapterService = null;
8174ae04c73312403e89db0f8e9bd9601d403b4783fredc        mRemoteDevices = null;
8274ae04c73312403e89db0f8e9bd9601d403b4783fredc        mAdapterProperties = null;
83ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
84ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
85ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class StableState extends State {
86ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
87ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
887aab11364743cbca6eeefecbbde19f0434aff362fredc            infoLog("StableState(): Entering Off State");
89ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
90ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
91ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
92ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
93b5cc776c9353a203cdde97e62b25f05d9633d14cfredc
94ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            BluetoothDevice dev = (BluetoothDevice)msg.obj;
956654f5c903de510a70f9e72cd5ad7837b615d93ffredc
96ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch(msg.what) {
976654f5c903de510a70f9e72cd5ad7837b615d93ffredc
98ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              case CREATE_BOND:
99ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  createBond(dev, true);
100ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  break;
101ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              case REMOVE_BOND:
102ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  removeBond(dev, true);
103ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                  break;
104ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              case BONDING_STATE_CHANGE:
105986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                int newState = msg.arg1;
106986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                /* if incoming pairing, transition to pending state */
107986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                if (newState == BluetoothDevice.BOND_BONDING)
108986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                {
109ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                    sendIntent(dev, newState, 0);
110986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                    transitionTo(mPendingCommandState);
111986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                }
112986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                else
113986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                {
114986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                    Log.e(TAG, "In stable state, received invalid newState: " + newState);
115986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                }
116986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                break;
117986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan
118986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan              case CANCEL_BOND:
119ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh              default:
120ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   Log.e(TAG, "Received unhandled state: " + msg.what);
121ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   return false;
122ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
123ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
124ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
125ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
126ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
127ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
128ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class PendingCommandState extends State {
129ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        private final ArrayList<BluetoothDevice> mDevices =
130ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            new ArrayList<BluetoothDevice>();
131ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
132ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
133ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
134ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            infoLog("Entering PendingCommandState State");
135ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            BluetoothDevice dev = (BluetoothDevice)getCurrentMessage().obj;
136ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
138ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
139ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
1407aab11364743cbca6eeefecbbde19f0434aff362fredc
141ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            BluetoothDevice dev = (BluetoothDevice)msg.obj;
142aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera            boolean result = false;
143ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (mDevices.contains(dev) &&
144ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    msg.what != CANCEL_BOND && msg.what != BONDING_STATE_CHANGE) {
145ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                deferMessage(msg);
146ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return true;
147ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
148ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
149ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch (msg.what) {
150ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case CREATE_BOND:
151ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    result = createBond(dev, false);
152ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
153ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case REMOVE_BOND:
154ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    result = removeBond(dev, false);
155ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
156ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case CANCEL_BOND:
157ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    result = cancelBond(dev);
158ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
159ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case BONDING_STATE_CHANGE:
160ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    int newState = msg.arg1;
161ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                    int reason = getUnbondReasonFromHALCode(msg.arg2);
162ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                    sendIntent(dev, newState, reason);
163aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera                    if(newState != BluetoothDevice.BOND_BONDING )
164986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                    {
165986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        /* this is either none/bonded, remove and transition */
166986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        result = !mDevices.remove(dev);
167986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        if (mDevices.isEmpty()) {
168c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // Whenever mDevices is empty, then we need to
169c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // set result=false. Else, we will end up adding
170c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // the device to the list again. This prevents us
171c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            // from pairing with a device that we just unpaired
172c181b8b49f5ad5b49b33334a9ba8f342ddb3545cKausik Sinnaswamy                            result = false;
173986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                            transitionTo(mStableState);
174986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                        }
1754f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        if (newState == BluetoothDevice.BOND_NONE)
1764f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        {
1774f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                            // Set the profile Priorities to undefined
1784f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                            clearProfilePriorty(dev);
1794f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        }
1804f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        else if (newState == BluetoothDevice.BOND_BONDED)
1814f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        {
1824f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                           // Restore the profile priorty settings
1834f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                           setProfilePriorty(dev);
1844f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta                        }
185ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    }
186aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera                    else if(!mDevices.contains(dev))
187aa90f0cbb860434c5310ae6bfa16987834f582f0Priti Aghera                        result=true;
188ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
189ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                default:
190ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    Log.e(TAG, "Received unhandled event:" + msg.what);
191ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    return false;
192ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
193ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (result) mDevices.add(dev);
194ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
195ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
196ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
197ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
198ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
199ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private boolean cancelBond(BluetoothDevice dev) {
200ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (dev.getBondState() == BluetoothDevice.BOND_BONDING) {
201ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
202ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (!mAdapterService.cancelBondNative(addr)) {
203ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               Log.e(TAG, "Unexpected error while cancelling bond:");
204ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else {
205ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return true;
206ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
207ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
208ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return false;
209ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
210ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
211ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private boolean removeBond(BluetoothDevice dev, boolean transition) {
212ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (dev.getBondState() == BluetoothDevice.BOND_BONDED) {
213ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
214ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (!mAdapterService.removeBondNative(addr)) {
215ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               Log.e(TAG, "Unexpected error while removing bond:");
216ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else {
217ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                if (transition) transitionTo(mPendingCommandState);
218ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return true;
219ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
220ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
221ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
222ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return false;
223ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
224ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
225ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private boolean createBond(BluetoothDevice dev, boolean transition) {
226ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
227ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            infoLog("Bond address is:" + dev);
228ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
229ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (!mAdapterService.createBondNative(addr)) {
230ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                sendIntent(dev, BluetoothDevice.BOND_NONE,
231ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan                           BluetoothDevice.UNBOND_REASON_REMOVED);
232986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan                return false;
233ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else if (transition) {
234ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                transitionTo(mPendingCommandState);
235ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
236ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
237ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
238ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return false;
239ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
240ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
241ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan    private void sendIntent(BluetoothDevice device, int newState, int reason) {
242ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        DeviceProperties devProp = mRemoteDevices.getDeviceProperties(device);
243179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        int oldState = BluetoothDevice.BOND_NONE;
244179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        if (devProp != null) {
245179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            oldState = devProp.getBondState();
246179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        }
247ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (oldState == newState) return;
248179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy        mAdapterProperties.onBondStateChanged(device, newState);
2492f9a79b2d545e1a8b50a0018456892a9934db99aRavi Nagarajan
250ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
251ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
252ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, newState);
253ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
254ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        if (newState == BluetoothDevice.BOND_NONE)
255ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            intent.putExtra(BluetoothDevice.EXTRA_REASON, reason);
256bd704c741b8c523ad747214f6f0520ac3e2caf8fZhihai Xu        mAdapterService.sendBroadcastAsUser(intent, UserHandle.ALL,
257bd704c741b8c523ad747214f6f0520ac3e2caf8fZhihai Xu                AdapterService.BLUETOOTH_PERM);
258ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        infoLog("Bond State Change Intent:" + device + " OldState: " + oldState
259ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                + " NewState: " + newState);
260ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
261ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
262ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    void bondStateChangeCallback(int status, byte[] address, int newState) {
263ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        BluetoothDevice device = mRemoteDevices.getDevice(address);
264ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
265ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (device == null) {
266179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            infoLog("No record of the device:" + device);
267179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            // This device will be added as part of the BONDING_STATE_CHANGE intent processing
268179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            // in sendIntent above
269179fd2512d1a93bbd2a1a3803f5764cb417fe4c9Kausik Sinnaswamy            device = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
270ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
271ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
272ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        infoLog("bondStateChangeCallback: Status: " + status + " Address: " + device
273ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                + " newState: " + newState);
274ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
275ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Message msg = obtainMessage(BONDING_STATE_CHANGE);
276ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        msg.obj = device;
277ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
278986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan        if (newState == BOND_STATE_BONDED)
279986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan            msg.arg1 = BluetoothDevice.BOND_BONDED;
280986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan        else if (newState == BOND_STATE_BONDING)
281986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan            msg.arg1 = BluetoothDevice.BOND_BONDING;
282986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan        else
283986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan            msg.arg1 = BluetoothDevice.BOND_NONE;
284ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        msg.arg2 = status;
285986b5b03a378385bfea6c5cc6b6c1d7f0424e0a5Ravi Nagarajan
286ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        sendMessage(msg);
287ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
288ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
2894f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    private void setProfilePriorty (BluetoothDevice device){
2904f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HidService hidService = HidService.getHidService();
2914f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        A2dpService a2dpService = A2dpService.getA2dpService();
2924f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HeadsetService headsetService = HeadsetService.getHeadsetService();
2934f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
2944f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if ((hidService != null) &&
2954f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
2964f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            hidService.setPriority(device,BluetoothProfile.PRIORITY_ON);
2974f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
2984f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
2994f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if ((a2dpService != null) &&
3004f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
3014f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            a2dpService.setPriority(device,BluetoothProfile.PRIORITY_ON);
3024f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
3034f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3044f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if ((headsetService != null) &&
3054f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            (headsetService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){
3064f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            headsetService.setPriority(device,BluetoothProfile.PRIORITY_ON);
3074f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        }
3084f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
3094f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3104f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    private void clearProfilePriorty (BluetoothDevice device){
3114f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HidService hidService = HidService.getHidService();
3124f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        A2dpService a2dpService = A2dpService.getA2dpService();
3134f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        HeadsetService headsetService = HeadsetService.getHeadsetService();
3144f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
3154f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if (hidService != null)
3164f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            hidService.setPriority(device,BluetoothProfile.PRIORITY_UNDEFINED);
3174f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if(a2dpService != null)
3184f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            a2dpService.setPriority(device,BluetoothProfile.PRIORITY_UNDEFINED);
3194f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta        if(headsetService != null)
3204f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            headsetService.setPriority(device,BluetoothProfile.PRIORITY_UNDEFINED);
3214f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta    }
3224f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta
323ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void infoLog(String msg) {
324ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Log.i(TAG, msg);
325ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
326ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
327ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void errorLog(String msg) {
328ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Log.e(TAG, msg);
329ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
33015d36984a79d6e35c659edb0efdf929f0b526bd5Fred
331ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan    private int getUnbondReasonFromHALCode (int reason) {
332ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        if (reason == AbstractionLayer.BT_STATUS_SUCCESS)
333ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            return BluetoothDevice.BOND_SUCCESS;
334ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        else if (reason == AbstractionLayer.BT_STATUS_RMT_DEV_DOWN)
335ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            return BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN;
336ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        else if (reason == AbstractionLayer.BT_STATUS_AUTH_FAILURE)
337ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan            return BluetoothDevice.UNBOND_REASON_AUTH_FAILED;
338ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan
339ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        /* default */
340ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan        return BluetoothDevice.UNBOND_REASON_REMOVED;
341ef39cada04683dd7ef7b68c89a8722f2ce635c28Ravi Nagarajan    }
342ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
343