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;
20ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.content.Context;
21ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.content.Intent;
22ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.os.Message;
23ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport android.util.Log;
24ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
25ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.internal.util.State;
26ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshimport com.android.internal.util.StateMachine;
27ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
28ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/**
29ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * This state machine handles Bluetooth Adapter State.
30ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * States:
31ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link OnState} : Bluetooth is on at this state
32ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link OffState}: Bluetooth is off at this state. This is the initial
33ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      state.
34ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh *      {@link PendingCommandState} : An enable / disable operation is pending.
35ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * TODO(BT): Add per process on state.
36ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
37ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
38ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshfinal class AdapterState extends StateMachine {
39fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie    private static final boolean DBG = false;
40ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private static final String TAG = "BluetoothAdapterState";
41ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
42ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int USER_TURN_ON = 1;
4331ba132491053bc86d419a7d51fc04af3299c076fredc    static final int STARTED=2;
4431ba132491053bc86d419a7d51fc04af3299c076fredc    static final int ENABLED_READY = 3;
45ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
4631ba132491053bc86d419a7d51fc04af3299c076fredc    static final int USER_TURN_OFF = 20;
4731ba132491053bc86d419a7d51fc04af3299c076fredc    static final int BEGIN_DISABLE = 21;
4831ba132491053bc86d419a7d51fc04af3299c076fredc    static final int ALL_DEVICES_DISCONNECTED = 22;
4974ae04c73312403e89db0f8e9bd9601d403b4783fredc
5031ba132491053bc86d419a7d51fc04af3299c076fredc    static final int DISABLED = 24;
5131ba132491053bc86d419a7d51fc04af3299c076fredc    static final int STOPPED=25;
52ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
5331ba132491053bc86d419a7d51fc04af3299c076fredc    static final int START_TIMEOUT = 100;
5431ba132491053bc86d419a7d51fc04af3299c076fredc    static final int ENABLE_TIMEOUT = 101;
5531ba132491053bc86d419a7d51fc04af3299c076fredc    static final int DISABLE_TIMEOUT = 103;
5631ba132491053bc86d419a7d51fc04af3299c076fredc    static final int STOP_TIMEOUT = 104;
5757a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie    static final int SET_SCAN_MODE_TIMEOUT = 105;
5831ba132491053bc86d419a7d51fc04af3299c076fredc
5931ba132491053bc86d419a7d51fc04af3299c076fredc    static final int USER_TURN_OFF_DELAY_MS=500;
6031ba132491053bc86d419a7d51fc04af3299c076fredc
6131ba132491053bc86d419a7d51fc04af3299c076fredc    //TODO: tune me
6231ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int ENABLE_TIMEOUT_DELAY = 8000;
6331ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int DISABLE_TIMEOUT_DELAY = 8000;
6431ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int START_TIMEOUT_DELAY = 5000;
6531ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int STOP_TIMEOUT_DELAY = 5000;
6631ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int PROPERTY_OP_DELAY =2000;
676654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterService mAdapterService;
686654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterProperties mAdapterProperties;
69ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private PendingCommandState mPendingCommandState = new PendingCommandState();
70ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private OnState mOnState = new OnState();
71ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private OffState mOffState = new OffState();
72ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
7331ba132491053bc86d419a7d51fc04af3299c076fredc    public boolean isTurningOn() {
7431ba132491053bc86d419a7d51fc04af3299c076fredc        boolean isTurningOn=  mPendingCommandState.isTurningOn();
7574ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (DBG) Log.d(TAG,"isTurningOn()=" + isTurningOn);
7631ba132491053bc86d419a7d51fc04af3299c076fredc        return isTurningOn;
77b5cc776c9353a203cdde97e62b25f05d9633d14cfredc    }
7831ba132491053bc86d419a7d51fc04af3299c076fredc
7931ba132491053bc86d419a7d51fc04af3299c076fredc    public boolean isTurningOff() {
8031ba132491053bc86d419a7d51fc04af3299c076fredc        boolean isTurningOff= mPendingCommandState.isTurningOff();
8174ae04c73312403e89db0f8e9bd9601d403b4783fredc        if (DBG) Log.d(TAG,"isTurningOff()=" + isTurningOff);
8231ba132491053bc86d419a7d51fc04af3299c076fredc        return isTurningOff;
8331ba132491053bc86d419a7d51fc04af3299c076fredc    }
8431ba132491053bc86d419a7d51fc04af3299c076fredc
856893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    private AdapterState(AdapterService service, AdapterProperties adapterProperties) {
86ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        super("BluetoothAdapterState:");
87ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mOnState);
88ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mOffState);
89ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mPendingCommandState);
90ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterService = service;
91ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterProperties = adapterProperties;
926654f5c903de510a70f9e72cd5ad7837b615d93ffredc        setInitialState(mOffState);
936654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
946654f5c903de510a70f9e72cd5ad7837b615d93ffredc
956893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    public static AdapterState make(AdapterService service, AdapterProperties adapterProperties) {
966893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        Log.d(TAG, "make");
976893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        AdapterState as = new AdapterState(service, adapterProperties);
986893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        as.start();
996893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        return as;
1006893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    }
10115d36984a79d6e35c659edb0efdf929f0b526bd5Fred
10215d36984a79d6e35c659edb0efdf929f0b526bd5Fred    public void doQuit() {
10315d36984a79d6e35c659edb0efdf929f0b526bd5Fred        quitNow();
10415d36984a79d6e35c659edb0efdf929f0b526bd5Fred    }
10515d36984a79d6e35c659edb0efdf929f0b526bd5Fred
1066654f5c903de510a70f9e72cd5ad7837b615d93ffredc    public void cleanup() {
1073fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mAdapterProperties != null)
1083fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mAdapterProperties = null;
1093fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mAdapterService != null)
1103fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mAdapterService = null;
111ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
112ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
113ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class OffState extends State {
114ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
115ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
11631ba132491053bc86d419a7d51fc04af3299c076fredc            infoLog("Entering OffState");
117ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
118ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
119ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
120ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
121b5cc776c9353a203cdde97e62b25f05d9633d14cfredc
122ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch(msg.what) {
123ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_ON:
12457a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");
1254852c5686229f1014e9851f4e9a3a19547581b45fredc                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);
12631ba132491053bc86d419a7d51fc04af3299c076fredc                   mPendingCommandState.setTurningOn(true);
12731ba132491053bc86d419a7d51fc04af3299c076fredc                   transitionTo(mPendingCommandState);
12831ba132491053bc86d419a7d51fc04af3299c076fredc                   sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);
12931ba132491053bc86d419a7d51fc04af3299c076fredc                   mAdapterService.processStart();
130ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
131ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_OFF:
13257a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_OFF");
13357a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   //TODO: Handle case of service started and stopped without enable
134ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
135ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               default:
13631ba132491053bc86d419a7d51fc04af3299c076fredc                   if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=OFF, MESSAGE = " + msg.what );
137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   return false;
138ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
139ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
140ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
141ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
142ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
143ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class OnState extends State {
144ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
145ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
146ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            infoLog("Entering On State");
1474f5430babbc5a8f870e5a578a4ea3452f41dd97aGanesh Ganapathi Batta            mAdapterService.autoConnect();
148ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
149ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
150ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
151ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
15215d36984a79d6e35c659edb0efdf929f0b526bd5Fred
153ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch(msg.what) {
154ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_OFF:
15557a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=ON, MESSAGE = USER_TURN_OFF");
1564852c5686229f1014e9851f4e9a3a19547581b45fredc                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF);
15731ba132491053bc86d419a7d51fc04af3299c076fredc                   mPendingCommandState.setTurningOff(true);
15831ba132491053bc86d419a7d51fc04af3299c076fredc                   transitionTo(mPendingCommandState);
15931ba132491053bc86d419a7d51fc04af3299c076fredc
160d570893c5ec3bc9fd1860aa0355c550d3a51f8ddKausik Sinnaswamy                   // Invoke onBluetoothDisable which shall trigger a
161d570893c5ec3bc9fd1860aa0355c550d3a51f8ddKausik Sinnaswamy                   // setScanMode to SCAN_MODE_NONE
16257a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   Message m = obtainMessage(SET_SCAN_MODE_TIMEOUT);
16331ba132491053bc86d419a7d51fc04af3299c076fredc                   sendMessageDelayed(m, PROPERTY_OP_DELAY);
164d570893c5ec3bc9fd1860aa0355c550d3a51f8ddKausik Sinnaswamy                   mAdapterProperties.onBluetoothDisable();
165ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
16631ba132491053bc86d419a7d51fc04af3299c076fredc
167ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_ON:
16857a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=ON, MESSAGE = USER_TURN_ON");
16931ba132491053bc86d419a7d51fc04af3299c076fredc                   Log.i(TAG,"Bluetooth already ON, ignoring USER_TURN_ON");
170ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
171ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               default:
17231ba132491053bc86d419a7d51fc04af3299c076fredc                   if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=ON, MESSAGE = " + msg.what );
173ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   return false;
174ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
175ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
176ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
177ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
178ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
179ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class PendingCommandState extends State {
18031ba132491053bc86d419a7d51fc04af3299c076fredc        private boolean mIsTurningOn;
18131ba132491053bc86d419a7d51fc04af3299c076fredc        private boolean mIsTurningOff;
18231ba132491053bc86d419a7d51fc04af3299c076fredc
183ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
18431ba132491053bc86d419a7d51fc04af3299c076fredc            infoLog("Entering PendingCommandState State: isTurningOn()=" + isTurningOn() + ", isTurningOff()=" + isTurningOff());
18531ba132491053bc86d419a7d51fc04af3299c076fredc        }
18631ba132491053bc86d419a7d51fc04af3299c076fredc
18731ba132491053bc86d419a7d51fc04af3299c076fredc        public void setTurningOn(boolean isTurningOn) {
18831ba132491053bc86d419a7d51fc04af3299c076fredc            mIsTurningOn = isTurningOn;
18931ba132491053bc86d419a7d51fc04af3299c076fredc        }
19031ba132491053bc86d419a7d51fc04af3299c076fredc
19131ba132491053bc86d419a7d51fc04af3299c076fredc        public boolean isTurningOn() {
19231ba132491053bc86d419a7d51fc04af3299c076fredc            return mIsTurningOn;
19331ba132491053bc86d419a7d51fc04af3299c076fredc        }
19431ba132491053bc86d419a7d51fc04af3299c076fredc
19531ba132491053bc86d419a7d51fc04af3299c076fredc        public void setTurningOff(boolean isTurningOff) {
19631ba132491053bc86d419a7d51fc04af3299c076fredc            mIsTurningOff = isTurningOff;
19731ba132491053bc86d419a7d51fc04af3299c076fredc        }
19831ba132491053bc86d419a7d51fc04af3299c076fredc
19931ba132491053bc86d419a7d51fc04af3299c076fredc        public boolean isTurningOff() {
20031ba132491053bc86d419a7d51fc04af3299c076fredc            return mIsTurningOff;
20131ba132491053bc86d419a7d51fc04af3299c076fredc        }
20231ba132491053bc86d419a7d51fc04af3299c076fredc
203ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
204ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
20515d36984a79d6e35c659edb0efdf929f0b526bd5Fred
20631ba132491053bc86d419a7d51fc04af3299c076fredc            boolean isTurningOn= isTurningOn();
20731ba132491053bc86d419a7d51fc04af3299c076fredc            boolean isTurningOff = isTurningOff();
20815d36984a79d6e35c659edb0efdf929f0b526bd5Fred
209ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch (msg.what) {
210ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case USER_TURN_ON:
21157a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = USER_TURN_ON"
21231ba132491053bc86d419a7d51fc04af3299c076fredc                            + ", isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
21331ba132491053bc86d419a7d51fc04af3299c076fredc                    if (isTurningOn) {
21431ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Alreadying turning on bluetooth... Ignoring USER_TURN_ON...");
21531ba132491053bc86d419a7d51fc04af3299c076fredc                    } else {
21631ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Deferring request USER_TURN_ON");
21731ba132491053bc86d419a7d51fc04af3299c076fredc                        deferMessage(msg);
21831ba132491053bc86d419a7d51fc04af3299c076fredc                    }
21931ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
220ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case USER_TURN_OFF:
22157a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = USER_TURN_ON"
22231ba132491053bc86d419a7d51fc04af3299c076fredc                            + ", isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
22331ba132491053bc86d419a7d51fc04af3299c076fredc                    if (isTurningOff) {
22431ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Alreadying turning off bluetooth... Ignoring USER_TURN_OFF...");
22531ba132491053bc86d419a7d51fc04af3299c076fredc                    } else {
22631ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Deferring request USER_TURN_OFF");
22731ba132491053bc86d419a7d51fc04af3299c076fredc                        deferMessage(msg);
22831ba132491053bc86d419a7d51fc04af3299c076fredc                    }
229ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
23031ba132491053bc86d419a7d51fc04af3299c076fredc                case STARTED:   {
23131ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
23231ba132491053bc86d419a7d51fc04af3299c076fredc                    //Remove start timeout
23331ba132491053bc86d419a7d51fc04af3299c076fredc                    removeMessages(START_TIMEOUT);
23431ba132491053bc86d419a7d51fc04af3299c076fredc
23531ba132491053bc86d419a7d51fc04af3299c076fredc                    //Enable
23631ba132491053bc86d419a7d51fc04af3299c076fredc                    boolean ret = mAdapterService.enableNative();
23731ba132491053bc86d419a7d51fc04af3299c076fredc                    if (!ret) {
23831ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.e(TAG, "Error while turning Bluetooth On");
2394852c5686229f1014e9851f4e9a3a19547581b45fredc                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
24031ba132491053bc86d419a7d51fc04af3299c076fredc                        transitionTo(mOffState);
24131ba132491053bc86d419a7d51fc04af3299c076fredc                    } else {
24231ba132491053bc86d419a7d51fc04af3299c076fredc                        sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
24331ba132491053bc86d419a7d51fc04af3299c076fredc                    }
24431ba132491053bc86d419a7d51fc04af3299c076fredc                }
24531ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
24631ba132491053bc86d419a7d51fc04af3299c076fredc
247ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case ENABLED_READY:
24831ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = ENABLE_READY, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
249ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    removeMessages(ENABLE_TIMEOUT);
250b5cc776c9353a203cdde97e62b25f05d9633d14cfredc                    mAdapterProperties.onBluetoothReady();
25131ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOn(false);
25231ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOnState);
2534852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
25431ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
25531ba132491053bc86d419a7d51fc04af3299c076fredc
25657a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                case SET_SCAN_MODE_TIMEOUT:
25757a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                     Log.w(TAG,"Timeout will setting scan mode..Continuing with disable...");
25857a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                     //Fall through
25931ba132491053bc86d419a7d51fc04af3299c076fredc                case BEGIN_DISABLE: {
26031ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = BEGIN_DISABLE" + isTurningOn + ", isTurningOff=" + isTurningOff);
26157a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                    removeMessages(SET_SCAN_MODE_TIMEOUT);
26231ba132491053bc86d419a7d51fc04af3299c076fredc                    sendMessageDelayed(DISABLE_TIMEOUT, DISABLE_TIMEOUT_DELAY);
26331ba132491053bc86d419a7d51fc04af3299c076fredc                    boolean ret = mAdapterService.disableNative();
26431ba132491053bc86d419a7d51fc04af3299c076fredc                    if (!ret) {
26531ba132491053bc86d419a7d51fc04af3299c076fredc                        removeMessages(DISABLE_TIMEOUT);
26631ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.e(TAG, "Error while turning Bluetooth Off");
26731ba132491053bc86d419a7d51fc04af3299c076fredc                        //FIXME: what about post enable services
26831ba132491053bc86d419a7d51fc04af3299c076fredc                        mPendingCommandState.setTurningOff(false);
2694852c5686229f1014e9851f4e9a3a19547581b45fredc                        notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
27031ba132491053bc86d419a7d51fc04af3299c076fredc                    }
27131ba132491053bc86d419a7d51fc04af3299c076fredc                }
272ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
273ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case DISABLED:
27431ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
27531ba132491053bc86d419a7d51fc04af3299c076fredc                    removeMessages(DISABLE_TIMEOUT);
27631ba132491053bc86d419a7d51fc04af3299c076fredc                    sendMessageDelayed(STOP_TIMEOUT, STOP_TIMEOUT_DELAY);
27731ba132491053bc86d419a7d51fc04af3299c076fredc                    if (mAdapterService.stopProfileServices()) {
27831ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.d(TAG,"Stopping profile services that were post enabled");
27931ba132491053bc86d419a7d51fc04af3299c076fredc                        break;
28031ba132491053bc86d419a7d51fc04af3299c076fredc                    }
28174ae04c73312403e89db0f8e9bd9601d403b4783fredc                    //Fall through if no services or services already stopped
28231ba132491053bc86d419a7d51fc04af3299c076fredc                case STOPPED:
28331ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOPPED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
28431ba132491053bc86d419a7d51fc04af3299c076fredc                    removeMessages(STOP_TIMEOUT);
28531ba132491053bc86d419a7d51fc04af3299c076fredc                    setTurningOff(false);
28631ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOffState);
2874852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
28831ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
28931ba132491053bc86d419a7d51fc04af3299c076fredc                case START_TIMEOUT:
29031ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = START_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
29131ba132491053bc86d419a7d51fc04af3299c076fredc                    errorLog("Error enabling Bluetooth");
29231ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOn(false);
293ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    transitionTo(mOffState);
2944852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
295ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
296ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case ENABLE_TIMEOUT:
29731ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = ENABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
298ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    errorLog("Error enabling Bluetooth");
29931ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOn(false);
300ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    transitionTo(mOffState);
3014852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
30231ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
30331ba132491053bc86d419a7d51fc04af3299c076fredc                case STOP_TIMEOUT:
30431ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOP_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
30531ba132491053bc86d419a7d51fc04af3299c076fredc                    errorLog("Error stopping Bluetooth profiles");
30631ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOff(false);
30731ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOffState);
30831ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
30931ba132491053bc86d419a7d51fc04af3299c076fredc                case DISABLE_TIMEOUT:
31031ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
31131ba132491053bc86d419a7d51fc04af3299c076fredc                    errorLog("Error disabling Bluetooth");
31231ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOff(false);
31331ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOnState);
314ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
315ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                default:
31631ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=PENDING, MESSAGE = " + msg.what );
317ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    return false;
318ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
319ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
320ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
321ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
322ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
323ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
3244852c5686229f1014e9851f4e9a3a19547581b45fredc    private void notifyAdapterStateChange(int newState) {
325ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        int oldState = mAdapterProperties.getState();
326ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterProperties.setState(newState);
3274852c5686229f1014e9851f4e9a3a19547581b45fredc        infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState);
3284852c5686229f1014e9851f4e9a3a19547581b45fredc        mAdapterService.updateAdapterState(oldState, newState);
329ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
330ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
331ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    void stateChangeCallback(int status) {
332ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (status == AbstractionLayer.BT_STATE_OFF) {
333ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            sendMessage(DISABLED);
334ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        } else if (status == AbstractionLayer.BT_STATE_ON) {
335ff68148a7fb74947ea5e7a337161108363cbe9f5Jaikumar Ganesh            // We should have got the property change for adapter and remote devices.
336ff68148a7fb74947ea5e7a337161108363cbe9f5Jaikumar Ganesh            sendMessage(ENABLED_READY);
337ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        } else {
338ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            errorLog("Incorrect status in stateChangeCallback");
339ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
340ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
341ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
342ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void infoLog(String msg) {
343ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (DBG) Log.i(TAG, msg);
344ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
345ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
346ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void errorLog(String msg) {
347ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Log.e(TAG, msg);
348ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
34915d36984a79d6e35c659edb0efdf929f0b526bd5Fred
350ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
351