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 {
3934e323baafb5563c3874f95847ec544faf6923f8Matthew Xie    private static final boolean DBG = true;
4034e323baafb5563c3874f95847ec544faf6923f8Matthew Xie    private static final boolean VDBG = false;
41ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private static final String TAG = "BluetoothAdapterState";
42ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
43ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    static final int USER_TURN_ON = 1;
4431ba132491053bc86d419a7d51fc04af3299c076fredc    static final int STARTED=2;
4531ba132491053bc86d419a7d51fc04af3299c076fredc    static final int ENABLED_READY = 3;
46ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
4731ba132491053bc86d419a7d51fc04af3299c076fredc    static final int USER_TURN_OFF = 20;
4831ba132491053bc86d419a7d51fc04af3299c076fredc    static final int BEGIN_DISABLE = 21;
4931ba132491053bc86d419a7d51fc04af3299c076fredc    static final int ALL_DEVICES_DISCONNECTED = 22;
5074ae04c73312403e89db0f8e9bd9601d403b4783fredc
5131ba132491053bc86d419a7d51fc04af3299c076fredc    static final int DISABLED = 24;
5231ba132491053bc86d419a7d51fc04af3299c076fredc    static final int STOPPED=25;
53ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
5431ba132491053bc86d419a7d51fc04af3299c076fredc    static final int START_TIMEOUT = 100;
5531ba132491053bc86d419a7d51fc04af3299c076fredc    static final int ENABLE_TIMEOUT = 101;
5631ba132491053bc86d419a7d51fc04af3299c076fredc    static final int DISABLE_TIMEOUT = 103;
5731ba132491053bc86d419a7d51fc04af3299c076fredc    static final int STOP_TIMEOUT = 104;
5857a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie    static final int SET_SCAN_MODE_TIMEOUT = 105;
5931ba132491053bc86d419a7d51fc04af3299c076fredc
6031ba132491053bc86d419a7d51fc04af3299c076fredc    static final int USER_TURN_OFF_DELAY_MS=500;
6131ba132491053bc86d419a7d51fc04af3299c076fredc
6231ba132491053bc86d419a7d51fc04af3299c076fredc    //TODO: tune me
6331ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int ENABLE_TIMEOUT_DELAY = 8000;
6431ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int DISABLE_TIMEOUT_DELAY = 8000;
6531ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int START_TIMEOUT_DELAY = 5000;
6631ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int STOP_TIMEOUT_DELAY = 5000;
6731ba132491053bc86d419a7d51fc04af3299c076fredc    private static final int PROPERTY_OP_DELAY =2000;
686654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterService mAdapterService;
696654f5c903de510a70f9e72cd5ad7837b615d93ffredc    private AdapterProperties mAdapterProperties;
70ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private PendingCommandState mPendingCommandState = new PendingCommandState();
71ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private OnState mOnState = new OnState();
72ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private OffState mOffState = new OffState();
73ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
7431ba132491053bc86d419a7d51fc04af3299c076fredc    public boolean isTurningOn() {
7531ba132491053bc86d419a7d51fc04af3299c076fredc        boolean isTurningOn=  mPendingCommandState.isTurningOn();
7634e323baafb5563c3874f95847ec544faf6923f8Matthew Xie        if (VDBG) Log.d(TAG,"isTurningOn()=" + isTurningOn);
7731ba132491053bc86d419a7d51fc04af3299c076fredc        return isTurningOn;
78b5cc776c9353a203cdde97e62b25f05d9633d14cfredc    }
7931ba132491053bc86d419a7d51fc04af3299c076fredc
8031ba132491053bc86d419a7d51fc04af3299c076fredc    public boolean isTurningOff() {
8131ba132491053bc86d419a7d51fc04af3299c076fredc        boolean isTurningOff= mPendingCommandState.isTurningOff();
8234e323baafb5563c3874f95847ec544faf6923f8Matthew Xie        if (VDBG) Log.d(TAG,"isTurningOff()=" + isTurningOff);
8331ba132491053bc86d419a7d51fc04af3299c076fredc        return isTurningOff;
8431ba132491053bc86d419a7d51fc04af3299c076fredc    }
8531ba132491053bc86d419a7d51fc04af3299c076fredc
866893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    private AdapterState(AdapterService service, AdapterProperties adapterProperties) {
87ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        super("BluetoothAdapterState:");
88ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mOnState);
89ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mOffState);
90ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        addState(mPendingCommandState);
91ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterService = service;
92ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        mAdapterProperties = adapterProperties;
936654f5c903de510a70f9e72cd5ad7837b615d93ffredc        setInitialState(mOffState);
946654f5c903de510a70f9e72cd5ad7837b615d93ffredc    }
956654f5c903de510a70f9e72cd5ad7837b615d93ffredc
966893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    public static AdapterState make(AdapterService service, AdapterProperties adapterProperties) {
976893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        Log.d(TAG, "make");
986893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        AdapterState as = new AdapterState(service, adapterProperties);
996893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        as.start();
1006893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville        return as;
1016893668d1ccf0cc6361ef31ace52fedc2e37e35aWink Saville    }
10215d36984a79d6e35c659edb0efdf929f0b526bd5Fred
10315d36984a79d6e35c659edb0efdf929f0b526bd5Fred    public void doQuit() {
10415d36984a79d6e35c659edb0efdf929f0b526bd5Fred        quitNow();
10515d36984a79d6e35c659edb0efdf929f0b526bd5Fred    }
10615d36984a79d6e35c659edb0efdf929f0b526bd5Fred
1076654f5c903de510a70f9e72cd5ad7837b615d93ffredc    public void cleanup() {
1083fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mAdapterProperties != null)
1093fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mAdapterProperties = null;
1103fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mAdapterService != null)
1113fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mAdapterService = null;
112ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
113ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
114ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class OffState extends State {
115ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
116ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
11731ba132491053bc86d419a7d51fc04af3299c076fredc            infoLog("Entering OffState");
118ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
119ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
120ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
121ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
1220eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            AdapterService adapterService = mAdapterService;
1230eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            if (adapterService == null) {
1240eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                Log.e(TAG,"receive message at OffState after cleanup:" +
1250eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                          msg.what);
1260eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                return false;
1270eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            }
128ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch(msg.what) {
129ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_ON:
13057a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");
1314852c5686229f1014e9851f4e9a3a19547581b45fredc                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);
13231ba132491053bc86d419a7d51fc04af3299c076fredc                   mPendingCommandState.setTurningOn(true);
13331ba132491053bc86d419a7d51fc04af3299c076fredc                   transitionTo(mPendingCommandState);
13431ba132491053bc86d419a7d51fc04af3299c076fredc                   sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);
1350eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                   adapterService.processStart();
136ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_OFF:
13857a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_OFF");
13957a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   //TODO: Handle case of service started and stopped without enable
140ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
141ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               default:
14231ba132491053bc86d419a7d51fc04af3299c076fredc                   if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=OFF, MESSAGE = " + msg.what );
143ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   return false;
144ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
145ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
146ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
147ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
148ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
149ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class OnState extends State {
150ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
151ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
152ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            infoLog("Entering On State");
1530eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            AdapterService adapterService = mAdapterService;
1540eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            if (adapterService == null) {
1550eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                Log.e(TAG,"enter OnState after cleanup");
1560eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                return;
1570eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            }
1580eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            adapterService.autoConnect();
159ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
160ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
161ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
162ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
1630eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            AdapterProperties adapterProperties = mAdapterProperties;
1640eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            if (adapterProperties == null) {
1650eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                Log.e(TAG,"receive message at OnState after cleanup:" +
1660eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                          msg.what);
1670eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                return false;
1680eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            }
16915d36984a79d6e35c659edb0efdf929f0b526bd5Fred
170ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch(msg.what) {
171ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_OFF:
17257a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=ON, MESSAGE = USER_TURN_OFF");
1734852c5686229f1014e9851f4e9a3a19547581b45fredc                   notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_OFF);
17431ba132491053bc86d419a7d51fc04af3299c076fredc                   mPendingCommandState.setTurningOff(true);
17531ba132491053bc86d419a7d51fc04af3299c076fredc                   transitionTo(mPendingCommandState);
17631ba132491053bc86d419a7d51fc04af3299c076fredc
177d570893c5ec3bc9fd1860aa0355c550d3a51f8ddKausik Sinnaswamy                   // Invoke onBluetoothDisable which shall trigger a
178d570893c5ec3bc9fd1860aa0355c550d3a51f8ddKausik Sinnaswamy                   // setScanMode to SCAN_MODE_NONE
17957a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   Message m = obtainMessage(SET_SCAN_MODE_TIMEOUT);
18031ba132491053bc86d419a7d51fc04af3299c076fredc                   sendMessageDelayed(m, PROPERTY_OP_DELAY);
1810eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                   adapterProperties.onBluetoothDisable();
182ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
18331ba132491053bc86d419a7d51fc04af3299c076fredc
184ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               case USER_TURN_ON:
18557a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                   if (DBG) Log.d(TAG,"CURRENT_STATE=ON, MESSAGE = USER_TURN_ON");
18631ba132491053bc86d419a7d51fc04af3299c076fredc                   Log.i(TAG,"Bluetooth already ON, ignoring USER_TURN_ON");
187ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   break;
188ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh               default:
18931ba132491053bc86d419a7d51fc04af3299c076fredc                   if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=ON, MESSAGE = " + msg.what );
190ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                   return false;
191ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
192ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
193ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
194ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
195ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
196ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private class PendingCommandState extends State {
19731ba132491053bc86d419a7d51fc04af3299c076fredc        private boolean mIsTurningOn;
19831ba132491053bc86d419a7d51fc04af3299c076fredc        private boolean mIsTurningOff;
19931ba132491053bc86d419a7d51fc04af3299c076fredc
200ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public void enter() {
20131ba132491053bc86d419a7d51fc04af3299c076fredc            infoLog("Entering PendingCommandState State: isTurningOn()=" + isTurningOn() + ", isTurningOff()=" + isTurningOff());
20231ba132491053bc86d419a7d51fc04af3299c076fredc        }
20331ba132491053bc86d419a7d51fc04af3299c076fredc
20431ba132491053bc86d419a7d51fc04af3299c076fredc        public void setTurningOn(boolean isTurningOn) {
20531ba132491053bc86d419a7d51fc04af3299c076fredc            mIsTurningOn = isTurningOn;
20631ba132491053bc86d419a7d51fc04af3299c076fredc        }
20731ba132491053bc86d419a7d51fc04af3299c076fredc
20831ba132491053bc86d419a7d51fc04af3299c076fredc        public boolean isTurningOn() {
20931ba132491053bc86d419a7d51fc04af3299c076fredc            return mIsTurningOn;
21031ba132491053bc86d419a7d51fc04af3299c076fredc        }
21131ba132491053bc86d419a7d51fc04af3299c076fredc
21231ba132491053bc86d419a7d51fc04af3299c076fredc        public void setTurningOff(boolean isTurningOff) {
21331ba132491053bc86d419a7d51fc04af3299c076fredc            mIsTurningOff = isTurningOff;
21431ba132491053bc86d419a7d51fc04af3299c076fredc        }
21531ba132491053bc86d419a7d51fc04af3299c076fredc
21631ba132491053bc86d419a7d51fc04af3299c076fredc        public boolean isTurningOff() {
21731ba132491053bc86d419a7d51fc04af3299c076fredc            return mIsTurningOff;
21831ba132491053bc86d419a7d51fc04af3299c076fredc        }
21931ba132491053bc86d419a7d51fc04af3299c076fredc
220ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        @Override
221ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        public boolean processMessage(Message msg) {
22215d36984a79d6e35c659edb0efdf929f0b526bd5Fred
22331ba132491053bc86d419a7d51fc04af3299c076fredc            boolean isTurningOn= isTurningOn();
22431ba132491053bc86d419a7d51fc04af3299c076fredc            boolean isTurningOff = isTurningOff();
22515d36984a79d6e35c659edb0efdf929f0b526bd5Fred
2260eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            AdapterService adapterService = mAdapterService;
2270eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            AdapterProperties adapterProperties = mAdapterProperties;
2280eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            if ((adapterService == null) || (adapterProperties == null)) {
2290eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                Log.e(TAG,"receive message at Pending State after cleanup:" +
2300eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                          msg.what);
2310eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                return false;
2320eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            }
2330eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu
234ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            switch (msg.what) {
235ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case USER_TURN_ON:
23657a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = USER_TURN_ON"
23731ba132491053bc86d419a7d51fc04af3299c076fredc                            + ", isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
23831ba132491053bc86d419a7d51fc04af3299c076fredc                    if (isTurningOn) {
23931ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Alreadying turning on bluetooth... Ignoring USER_TURN_ON...");
24031ba132491053bc86d419a7d51fc04af3299c076fredc                    } else {
24131ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Deferring request USER_TURN_ON");
24231ba132491053bc86d419a7d51fc04af3299c076fredc                        deferMessage(msg);
24331ba132491053bc86d419a7d51fc04af3299c076fredc                    }
24431ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
245ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case USER_TURN_OFF:
24657a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = USER_TURN_ON"
24731ba132491053bc86d419a7d51fc04af3299c076fredc                            + ", isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
24831ba132491053bc86d419a7d51fc04af3299c076fredc                    if (isTurningOff) {
24931ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Alreadying turning off bluetooth... Ignoring USER_TURN_OFF...");
25031ba132491053bc86d419a7d51fc04af3299c076fredc                    } else {
25131ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.i(TAG,"CURRENT_STATE=PENDING: Deferring request USER_TURN_OFF");
25231ba132491053bc86d419a7d51fc04af3299c076fredc                        deferMessage(msg);
25331ba132491053bc86d419a7d51fc04af3299c076fredc                    }
254ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
25531ba132491053bc86d419a7d51fc04af3299c076fredc                case STARTED:   {
25631ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
25731ba132491053bc86d419a7d51fc04af3299c076fredc                    //Remove start timeout
25831ba132491053bc86d419a7d51fc04af3299c076fredc                    removeMessages(START_TIMEOUT);
25931ba132491053bc86d419a7d51fc04af3299c076fredc
26031ba132491053bc86d419a7d51fc04af3299c076fredc                    //Enable
2610eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                    boolean ret = adapterService.enableNative();
26231ba132491053bc86d419a7d51fc04af3299c076fredc                    if (!ret) {
26331ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.e(TAG, "Error while turning Bluetooth On");
2644852c5686229f1014e9851f4e9a3a19547581b45fredc                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
26531ba132491053bc86d419a7d51fc04af3299c076fredc                        transitionTo(mOffState);
26631ba132491053bc86d419a7d51fc04af3299c076fredc                    } else {
26731ba132491053bc86d419a7d51fc04af3299c076fredc                        sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
26831ba132491053bc86d419a7d51fc04af3299c076fredc                    }
26931ba132491053bc86d419a7d51fc04af3299c076fredc                }
27031ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
27131ba132491053bc86d419a7d51fc04af3299c076fredc
272ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case ENABLED_READY:
27331ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = ENABLE_READY, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
274ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    removeMessages(ENABLE_TIMEOUT);
2750eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                    adapterProperties.onBluetoothReady();
27631ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOn(false);
27731ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOnState);
2784852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
27931ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
28031ba132491053bc86d419a7d51fc04af3299c076fredc
28157a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                case SET_SCAN_MODE_TIMEOUT:
28257a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                     Log.w(TAG,"Timeout will setting scan mode..Continuing with disable...");
28357a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                     //Fall through
28431ba132491053bc86d419a7d51fc04af3299c076fredc                case BEGIN_DISABLE: {
285ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = BEGIN_DISABLE, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
28657a3923845c46742ed4f03d49dbdbb6c774ccf90Matthew Xie                    removeMessages(SET_SCAN_MODE_TIMEOUT);
28731ba132491053bc86d419a7d51fc04af3299c076fredc                    sendMessageDelayed(DISABLE_TIMEOUT, DISABLE_TIMEOUT_DELAY);
2880eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                    boolean ret = adapterService.disableNative();
28931ba132491053bc86d419a7d51fc04af3299c076fredc                    if (!ret) {
29031ba132491053bc86d419a7d51fc04af3299c076fredc                        removeMessages(DISABLE_TIMEOUT);
29131ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.e(TAG, "Error while turning Bluetooth Off");
29231ba132491053bc86d419a7d51fc04af3299c076fredc                        //FIXME: what about post enable services
29331ba132491053bc86d419a7d51fc04af3299c076fredc                        mPendingCommandState.setTurningOff(false);
2944852c5686229f1014e9851f4e9a3a19547581b45fredc                        notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
29531ba132491053bc86d419a7d51fc04af3299c076fredc                    }
29631ba132491053bc86d419a7d51fc04af3299c076fredc                }
297ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
298ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case DISABLED:
29931ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
300ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                    if (isTurningOn) {
301ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                        removeMessages(ENABLE_TIMEOUT);
302ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                        errorLog("Error enabling Bluetooth - hardware init failed");
303ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                        mPendingCommandState.setTurningOn(false);
304ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                        transitionTo(mOffState);
3050eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                        adapterService.stopProfileServices();
306ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                        notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
307ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                        break;
308ad9fff218081d2f49471487d37387c764d69ed29YK Jeffrey Chao                    }
30931ba132491053bc86d419a7d51fc04af3299c076fredc                    removeMessages(DISABLE_TIMEOUT);
31031ba132491053bc86d419a7d51fc04af3299c076fredc                    sendMessageDelayed(STOP_TIMEOUT, STOP_TIMEOUT_DELAY);
3110eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu                    if (adapterService.stopProfileServices()) {
31231ba132491053bc86d419a7d51fc04af3299c076fredc                        Log.d(TAG,"Stopping profile services that were post enabled");
31331ba132491053bc86d419a7d51fc04af3299c076fredc                        break;
31431ba132491053bc86d419a7d51fc04af3299c076fredc                    }
31574ae04c73312403e89db0f8e9bd9601d403b4783fredc                    //Fall through if no services or services already stopped
31631ba132491053bc86d419a7d51fc04af3299c076fredc                case STOPPED:
31731ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOPPED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
31831ba132491053bc86d419a7d51fc04af3299c076fredc                    removeMessages(STOP_TIMEOUT);
31931ba132491053bc86d419a7d51fc04af3299c076fredc                    setTurningOff(false);
32031ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOffState);
3214852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
32231ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
32331ba132491053bc86d419a7d51fc04af3299c076fredc                case START_TIMEOUT:
32431ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = START_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
32531ba132491053bc86d419a7d51fc04af3299c076fredc                    errorLog("Error enabling Bluetooth");
32631ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOn(false);
327ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    transitionTo(mOffState);
3284852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
329ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
330ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                case ENABLE_TIMEOUT:
33131ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = ENABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
332ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    errorLog("Error enabling Bluetooth");
33331ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOn(false);
334ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    transitionTo(mOffState);
3354852c5686229f1014e9851f4e9a3a19547581b45fredc                    notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
33631ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
33731ba132491053bc86d419a7d51fc04af3299c076fredc                case STOP_TIMEOUT:
33831ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOP_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
33931ba132491053bc86d419a7d51fc04af3299c076fredc                    errorLog("Error stopping Bluetooth profiles");
34031ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOff(false);
34131ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOffState);
34231ba132491053bc86d419a7d51fc04af3299c076fredc                    break;
34331ba132491053bc86d419a7d51fc04af3299c076fredc                case DISABLE_TIMEOUT:
34431ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = DISABLE_TIMEOUT, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
34531ba132491053bc86d419a7d51fc04af3299c076fredc                    errorLog("Error disabling Bluetooth");
34631ba132491053bc86d419a7d51fc04af3299c076fredc                    mPendingCommandState.setTurningOff(false);
34731ba132491053bc86d419a7d51fc04af3299c076fredc                    transitionTo(mOnState);
348865b323bb1d0aa9581a9b6a2f5ed96fc0ee70b23Matthew Xie                    notifyAdapterStateChange(BluetoothAdapter.STATE_ON);
349ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    break;
350ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                default:
35131ba132491053bc86d419a7d51fc04af3299c076fredc                    if (DBG) Log.d(TAG,"ERROR: UNEXPECTED MESSAGE: CURRENT_STATE=PENDING, MESSAGE = " + msg.what );
352ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                    return false;
353ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
354ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return true;
355ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
356ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
357ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
358ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
3594852c5686229f1014e9851f4e9a3a19547581b45fredc    private void notifyAdapterStateChange(int newState) {
3600eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        AdapterService adapterService = mAdapterService;
3610eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        AdapterProperties adapterProperties = mAdapterProperties;
3620eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        if ((adapterService == null) || (adapterProperties == null)) {
3630eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            Log.e(TAG,"notifyAdapterStateChange after cleanup:" + newState);
3640eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu            return;
3650eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        }
3660eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu
3670eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        int oldState = adapterProperties.getState();
3680eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        adapterProperties.setState(newState);
3694852c5686229f1014e9851f4e9a3a19547581b45fredc        infoLog("Bluetooth adapter state changed: " + oldState + "-> " + newState);
3700eea1282dcb425c1ea9dc6aa08d323884a9a1655Zhihai Xu        adapterService.updateAdapterState(oldState, newState);
371ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
372ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
373ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    void stateChangeCallback(int status) {
374ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (status == AbstractionLayer.BT_STATE_OFF) {
375ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            sendMessage(DISABLED);
376ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        } else if (status == AbstractionLayer.BT_STATE_ON) {
377ff68148a7fb74947ea5e7a337161108363cbe9f5Jaikumar Ganesh            // We should have got the property change for adapter and remote devices.
378ff68148a7fb74947ea5e7a337161108363cbe9f5Jaikumar Ganesh            sendMessage(ENABLED_READY);
379ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        } else {
380ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            errorLog("Incorrect status in stateChangeCallback");
381ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
382ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
383ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
384ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void infoLog(String msg) {
385ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (DBG) Log.i(TAG, msg);
386ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
387ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
388ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    private void errorLog(String msg) {
389ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        Log.e(TAG, msg);
390ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
39115d36984a79d6e35c659edb0efdf929f0b526bd5Fred
392ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
393