• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.btservice;
18 
19 import android.bluetooth.BluetoothAdapter;
20 import android.bluetooth.BluetoothDevice;
21 import android.bluetooth.BluetoothProfile;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.ParcelUuid;
25 import android.os.UserHandle;
26 import android.util.Log;
27 import android.util.Pair;
28 
29 import com.android.bluetooth.Utils;
30 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
31 
32 import java.util.HashMap;
33 import java.util.ArrayList;
34 import java.util.concurrent.CopyOnWriteArrayList;
35 
36 class AdapterProperties {
37     private static final boolean DBG = true;
38     private static final boolean VDBG = false;
39     private static final String TAG = "BluetoothAdapterProperties";
40 
41     private static final int BD_ADDR_LEN = 6; // 6 bytes
42     private String mName;
43     private byte[] mAddress;
44     private int mBluetoothClass;
45     private int mScanMode;
46     private int mDiscoverableTimeout;
47     private ParcelUuid[] mUuids;
48     private CopyOnWriteArrayList<BluetoothDevice> mBondedDevices = new CopyOnWriteArrayList<BluetoothDevice>();
49 
50     private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting;
51     private HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState;
52 
53 
54     private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
55     private int mState = BluetoothAdapter.STATE_OFF;
56 
57     private AdapterService mService;
58     private boolean mDiscovering;
59     private RemoteDevices mRemoteDevices;
60     private BluetoothAdapter mAdapter;
61     //TODO - all hw capabilities to be exposed as a class
62     private int mNumOfAdvertisementInstancesSupported;
63     private boolean mRpaOffloadSupported;
64     private int mNumOfOffloadedIrkSupported;
65     private int mNumOfOffloadedScanFilterSupported;
66     private int mOffloadedScanResultStorageBytes;
67     private int mVersSupported;
68     private int mTotNumOfTrackableAdv;
69     private boolean mIsExtendedScanSupported;
70     private boolean mIsDebugLogSupported;
71     private boolean mIsActivityAndEnergyReporting;
72 
73     // Lock for all getters and setters.
74     // If finer grained locking is needer, more locks
75     // can be added here.
76     private Object mObject = new Object();
77 
AdapterProperties(AdapterService service)78     public AdapterProperties(AdapterService service) {
79         mService = service;
80         mAdapter = BluetoothAdapter.getDefaultAdapter();
81     }
init(RemoteDevices remoteDevices)82     public void init(RemoteDevices remoteDevices) {
83         if (mProfileConnectionState ==null) {
84             mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>();
85         } else {
86             mProfileConnectionState.clear();
87         }
88         mRemoteDevices = remoteDevices;
89     }
90 
cleanup()91     public void cleanup() {
92         mRemoteDevices = null;
93         if (mProfileConnectionState != null) {
94             mProfileConnectionState.clear();
95             mProfileConnectionState = null;
96         }
97         mService = null;
98         if (!mBondedDevices.isEmpty())
99             mBondedDevices.clear();
100     }
101 
102     @Override
clone()103     public Object clone() throws CloneNotSupportedException {
104         throw new CloneNotSupportedException();
105     }
106 
107     /**
108      * @return the mName
109      */
getName()110     String getName() {
111         synchronized (mObject) {
112             return mName;
113         }
114     }
115 
116     /**
117      * Set the local adapter property - name
118      * @param name the name to set
119      */
setName(String name)120     boolean setName(String name) {
121         synchronized (mObject) {
122             return mService.setAdapterPropertyNative(
123                     AbstractionLayer.BT_PROPERTY_BDNAME, name.getBytes());
124         }
125     }
126 
127     /**
128      * @return the mClass
129      */
getBluetoothClass()130     int getBluetoothClass() {
131         synchronized (mObject) {
132             return mBluetoothClass;
133         }
134     }
135 
136     /**
137      * @return the mScanMode
138      */
getScanMode()139     int getScanMode() {
140         synchronized (mObject) {
141             return mScanMode;
142         }
143     }
144 
145     /**
146      * Set the local adapter property - scanMode
147      *
148      * @param scanMode the ScanMode to set
149      */
setScanMode(int scanMode)150     boolean setScanMode(int scanMode) {
151         synchronized (mObject) {
152             return mService.setAdapterPropertyNative(
153                     AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE, Utils.intToByteArray(scanMode));
154         }
155     }
156 
157     /**
158      * @return the mUuids
159      */
getUuids()160     ParcelUuid[] getUuids() {
161         synchronized (mObject) {
162             return mUuids;
163         }
164     }
165 
166     /**
167      * Set local adapter UUIDs.
168      *
169      * @param uuids the uuids to be set.
170      */
setUuids(ParcelUuid[] uuids)171     boolean setUuids(ParcelUuid[] uuids) {
172         synchronized (mObject) {
173             return mService.setAdapterPropertyNative(
174                     AbstractionLayer.BT_PROPERTY_UUIDS, Utils.uuidsToByteArray(uuids));
175         }
176     }
177 
178     /**
179      * @return the mAddress
180      */
getAddress()181     byte[] getAddress() {
182         synchronized (mObject) {
183             return mAddress;
184         }
185     }
186 
187     /**
188      * @param mConnectionState the mConnectionState to set
189      */
setConnectionState(int mConnectionState)190     void setConnectionState(int mConnectionState) {
191         synchronized (mObject) {
192             this.mConnectionState = mConnectionState;
193         }
194     }
195 
196     /**
197      * @return the mConnectionState
198      */
getConnectionState()199     int getConnectionState() {
200         synchronized (mObject) {
201             return mConnectionState;
202         }
203     }
204 
205     /**
206      * @param mState the mState to set
207      */
setState(int mState)208     void setState(int mState) {
209         synchronized (mObject) {
210             debugLog("Setting state to " + mState);
211             this.mState = mState;
212         }
213     }
214 
215     /**
216      * @return the mState
217      */
getState()218     int getState() {
219         /* remove the lock to work around a platform deadlock problem */
220         /* and also for read access, it is safe to remove the lock to save CPU power */
221         return mState;
222     }
223 
224     /**
225      * @return the mNumOfAdvertisementInstancesSupported
226      */
getNumOfAdvertisementInstancesSupported()227     int getNumOfAdvertisementInstancesSupported() {
228         return mNumOfAdvertisementInstancesSupported;
229     }
230 
231     /**
232      * @return the mRpaOffloadSupported
233      */
isRpaOffloadSupported()234     boolean isRpaOffloadSupported() {
235         return mRpaOffloadSupported;
236     }
237 
238     /**
239      * @return the mNumOfOffloadedIrkSupported
240      */
getNumOfOffloadedIrkSupported()241     int getNumOfOffloadedIrkSupported() {
242         return mNumOfOffloadedIrkSupported;
243     }
244 
245     /**
246      * @return the mNumOfOffloadedScanFilterSupported
247      */
getNumOfOffloadedScanFilterSupported()248     int getNumOfOffloadedScanFilterSupported() {
249         return mNumOfOffloadedScanFilterSupported;
250     }
251 
252     /**
253      * @return the mOffloadedScanResultStorageBytes
254      */
getOffloadedScanResultStorage()255     int getOffloadedScanResultStorage() {
256         return mOffloadedScanResultStorageBytes;
257     }
258 
259     /**
260      * @return tx/rx/idle activity and energy info
261      */
isActivityAndEnergyReportingSupported()262     boolean isActivityAndEnergyReportingSupported() {
263         return mIsActivityAndEnergyReporting;
264     }
265 
266     /**
267      * @return total number of trackable advertisements
268      */
getTotalNumOfTrackableAdvertisements()269     int getTotalNumOfTrackableAdvertisements() {
270         return mTotNumOfTrackableAdv;
271     }
272 
273     /**
274      * @return the mBondedDevices
275      */
getBondedDevices()276     BluetoothDevice[] getBondedDevices() {
277         BluetoothDevice[] bondedDeviceList = new BluetoothDevice[0];
278         synchronized (mObject) {
279             if(mBondedDevices.isEmpty())
280                 return (new BluetoothDevice[0]);
281 
282             try {
283                 bondedDeviceList = mBondedDevices.toArray(bondedDeviceList);
284                 infoLog("getBondedDevices: length="+bondedDeviceList.length);
285                 return bondedDeviceList;
286             } catch(ArrayStoreException ee) {
287                 errorLog("Error retrieving bonded device array");
288                 return (new BluetoothDevice[0]);
289             }
290         }
291     }
292     // This function shall be invoked from BondStateMachine whenever the bond
293     // state changes.
onBondStateChanged(BluetoothDevice device, int state)294     void onBondStateChanged(BluetoothDevice device, int state)
295     {
296         if(device == null)
297             return;
298         try {
299             byte[] addrByte = Utils.getByteAddress(device);
300             DeviceProperties prop = mRemoteDevices.getDeviceProperties(device);
301             if (prop == null)
302                 prop = mRemoteDevices.addDeviceProperties(addrByte);
303             prop.setBondState(state);
304 
305             if (state == BluetoothDevice.BOND_BONDED) {
306                 // add if not already in list
307                 if(!mBondedDevices.contains(device)) {
308                     debugLog("Adding bonded device:" +  device);
309                     mBondedDevices.add(device);
310                 }
311             } else if (state == BluetoothDevice.BOND_NONE) {
312                 // remove device from list
313                 if (mBondedDevices.remove(device))
314                     debugLog("Removing bonded device:" +  device);
315                 else
316                     debugLog("Failed to remove device: " + device);
317             }
318         }
319         catch(Exception ee) {
320             Log.e(TAG, "Exception in onBondStateChanged : ", ee);
321         }
322     }
323 
getDiscoverableTimeout()324     int getDiscoverableTimeout() {
325         synchronized (mObject) {
326             return mDiscoverableTimeout;
327         }
328     }
329 
setDiscoverableTimeout(int timeout)330     boolean setDiscoverableTimeout(int timeout) {
331         synchronized (mObject) {
332             return mService.setAdapterPropertyNative(
333                     AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT,
334                     Utils.intToByteArray(timeout));
335         }
336     }
337 
getProfileConnectionState(int profile)338     int getProfileConnectionState(int profile) {
339         synchronized (mObject) {
340             Pair<Integer, Integer> p = mProfileConnectionState.get(profile);
341             if (p != null) return p.first;
342             return BluetoothProfile.STATE_DISCONNECTED;
343         }
344     }
345 
isDiscovering()346     boolean isDiscovering() {
347         synchronized (mObject) {
348             return mDiscovering;
349         }
350     }
351 
sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)352     void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
353         if (!validateProfileConnectionState(state) ||
354                 !validateProfileConnectionState(prevState)) {
355             // Previously, an invalid state was broadcast anyway,
356             // with the invalid state converted to -1 in the intent.
357             // Better to log an error and not send an intent with
358             // invalid contents or set mAdapterConnectionState to -1.
359             errorLog("Error in sendConnectionStateChange: "
360                     + "prevState " + prevState + " state " + state);
361             return;
362         }
363 
364         synchronized (mObject) {
365             updateProfileConnectionState(profile, state, prevState);
366 
367             if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
368                 setConnectionState(state);
369 
370                 Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
371                 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
372                 intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
373                         convertToAdapterState(state));
374                 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
375                         convertToAdapterState(prevState));
376                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
377                 mService.sendBroadcastAsUser(intent, UserHandle.ALL,
378                         mService.BLUETOOTH_PERM);
379                 Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
380                         + prevState + " -> " + state);
381             }
382         }
383     }
384 
validateProfileConnectionState(int state)385     private boolean validateProfileConnectionState(int state) {
386         return (state == BluetoothProfile.STATE_DISCONNECTED ||
387                 state == BluetoothProfile.STATE_CONNECTING ||
388                 state == BluetoothProfile.STATE_CONNECTED ||
389                 state == BluetoothProfile.STATE_DISCONNECTING);
390     }
391 
392 
convertToAdapterState(int state)393     private int convertToAdapterState(int state) {
394         switch (state) {
395             case BluetoothProfile.STATE_DISCONNECTED:
396                 return BluetoothAdapter.STATE_DISCONNECTED;
397             case BluetoothProfile.STATE_DISCONNECTING:
398                 return BluetoothAdapter.STATE_DISCONNECTING;
399             case BluetoothProfile.STATE_CONNECTED:
400                 return BluetoothAdapter.STATE_CONNECTED;
401             case BluetoothProfile.STATE_CONNECTING:
402                 return BluetoothAdapter.STATE_CONNECTING;
403         }
404         Log.e(TAG, "Error in convertToAdapterState");
405         return -1;
406     }
407 
updateCountersAndCheckForConnectionStateChange(int state, int prevState)408     private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
409         switch (prevState) {
410             case BluetoothProfile.STATE_CONNECTING:
411                 mProfilesConnecting--;
412                 break;
413 
414             case BluetoothProfile.STATE_CONNECTED:
415                 mProfilesConnected--;
416                 break;
417 
418             case BluetoothProfile.STATE_DISCONNECTING:
419                 mProfilesDisconnecting--;
420                 break;
421         }
422 
423         switch (state) {
424             case BluetoothProfile.STATE_CONNECTING:
425                 mProfilesConnecting++;
426                 return (mProfilesConnected == 0 && mProfilesConnecting == 1);
427 
428             case BluetoothProfile.STATE_CONNECTED:
429                 mProfilesConnected++;
430                 return (mProfilesConnected == 1);
431 
432             case BluetoothProfile.STATE_DISCONNECTING:
433                 mProfilesDisconnecting++;
434                 return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
435 
436             case BluetoothProfile.STATE_DISCONNECTED:
437                 return (mProfilesConnected == 0 && mProfilesConnecting == 0);
438 
439             default:
440                 return true;
441         }
442     }
443 
updateProfileConnectionState(int profile, int newState, int oldState)444     private void updateProfileConnectionState(int profile, int newState, int oldState) {
445         // mProfileConnectionState is a hashmap -
446         // <Integer, Pair<Integer, Integer>>
447         // The key is the profile, the value is a pair. first element
448         // is the state and the second element is the number of devices
449         // in that state.
450         int numDev = 1;
451         int newHashState = newState;
452         boolean update = true;
453 
454         // The following conditions are considered in this function:
455         // 1. If there is no record of profile and state - update
456         // 2. If a new device's state is current hash state - increment
457         //    number of devices in the state.
458         // 3. If a state change has happened to Connected or Connecting
459         //    (if current state is not connected), update.
460         // 4. If numDevices is 1 and that device state is being updated, update
461         // 5. If numDevices is > 1 and one of the devices is changing state,
462         //    decrement numDevices but maintain oldState if it is Connected or
463         //    Connecting
464         Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
465         if (stateNumDev != null) {
466             int currHashState = stateNumDev.first;
467             numDev = stateNumDev.second;
468 
469             if (newState == currHashState) {
470                 numDev ++;
471             } else if (newState == BluetoothProfile.STATE_CONNECTED ||
472                    (newState == BluetoothProfile.STATE_CONNECTING &&
473                     currHashState != BluetoothProfile.STATE_CONNECTED)) {
474                  numDev = 1;
475             } else if (numDev == 1 && oldState == currHashState) {
476                  update = true;
477             } else if (numDev > 1 && oldState == currHashState) {
478                  numDev --;
479 
480                  if (currHashState == BluetoothProfile.STATE_CONNECTED ||
481                      currHashState == BluetoothProfile.STATE_CONNECTING) {
482                     newHashState = currHashState;
483                  }
484             } else {
485                  update = false;
486             }
487         }
488 
489         if (update) {
490             mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState,
491                     numDev));
492         }
493     }
494 
adapterPropertyChangedCallback(int[] types, byte[][] values)495     void adapterPropertyChangedCallback(int[] types, byte[][] values) {
496         Intent intent;
497         int type;
498         byte[] val;
499         for (int i = 0; i < types.length; i++) {
500             val = values[i];
501             type = types[i];
502             infoLog("adapterPropertyChangedCallback with type:" + type + " len:" + val.length);
503             synchronized (mObject) {
504                 switch (type) {
505                     case AbstractionLayer.BT_PROPERTY_BDNAME:
506                         mName = new String(val);
507                         intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
508                         intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
509                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
510                         mService.sendBroadcastAsUser(intent, UserHandle.ALL,
511                                  mService.BLUETOOTH_PERM);
512                         debugLog("Name is: " + mName);
513                         break;
514                     case AbstractionLayer.BT_PROPERTY_BDADDR:
515                         mAddress = val;
516                         debugLog("Address is:" + Utils.getAddressStringFromByte(mAddress));
517                         break;
518                     case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE:
519                         mBluetoothClass = Utils.byteArrayToInt(val, 0);
520                         debugLog("BT Class:" + mBluetoothClass);
521                         break;
522                     case AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE:
523                         int mode = Utils.byteArrayToInt(val, 0);
524                         mScanMode = mService.convertScanModeFromHal(mode);
525                         intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
526                         intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode);
527                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
528                         mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
529                         debugLog("Scan Mode:" + mScanMode);
530                         if (mBluetoothDisabling) {
531                             mBluetoothDisabling=false;
532                             mService.startBluetoothDisable();
533                         }
534                         break;
535                     case AbstractionLayer.BT_PROPERTY_UUIDS:
536                         mUuids = Utils.byteArrayToUuid(val);
537                         break;
538                     case AbstractionLayer.BT_PROPERTY_ADAPTER_BONDED_DEVICES:
539                         int number = val.length/BD_ADDR_LEN;
540                         byte[] addrByte = new byte[BD_ADDR_LEN];
541                         for (int j = 0; j < number; j++) {
542                             System.arraycopy(val, j * BD_ADDR_LEN, addrByte, 0, BD_ADDR_LEN);
543                             onBondStateChanged(mAdapter.getRemoteDevice(
544                                                Utils.getAddressStringFromByte(addrByte)),
545                                                BluetoothDevice.BOND_BONDED);
546                         }
547                         break;
548                     case AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT:
549                         mDiscoverableTimeout = Utils.byteArrayToInt(val, 0);
550                         debugLog("Discoverable Timeout:" + mDiscoverableTimeout);
551                         break;
552 
553                     case AbstractionLayer.BT_PROPERTY_LOCAL_LE_FEATURES:
554                         updateFeatureSupport(val);
555                         break;
556 
557                     default:
558                         errorLog("Property change not handled in Java land:" + type);
559                 }
560             }
561         }
562     }
563 
updateFeatureSupport(byte[] val)564     void updateFeatureSupport(byte[] val) {
565         mVersSupported = ((0xFF & ((int)val[1])) << 8)
566                             + (0xFF & ((int)val[0]));
567         mNumOfAdvertisementInstancesSupported = (0xFF & ((int)val[3]));
568         mRpaOffloadSupported = ((0xFF & ((int)val[4]))!= 0);
569         mNumOfOffloadedIrkSupported =  (0xFF & ((int)val[5]));
570         mNumOfOffloadedScanFilterSupported = (0xFF & ((int)val[6]));
571         mIsActivityAndEnergyReporting = ((0xFF & ((int)val[7])) != 0);
572         mOffloadedScanResultStorageBytes = ((0xFF & ((int)val[9])) << 8)
573                             + (0xFF & ((int)val[8]));
574         mTotNumOfTrackableAdv = ((0xFF & ((int)val[11])) << 8)
575                             + (0xFF & ((int)val[10]));
576         mIsExtendedScanSupported = ((0xFF & ((int)val[12])) != 0);
577         mIsDebugLogSupported = ((0xFF & ((int)val[13])) != 0);
578 
579         Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller"
580                 + " mNumOfAdvertisementInstancesSupported = "
581                 + mNumOfAdvertisementInstancesSupported
582                 + " mRpaOffloadSupported = " + mRpaOffloadSupported
583                 + " mNumOfOffloadedIrkSupported = "
584                 + mNumOfOffloadedIrkSupported
585                 + " mNumOfOffloadedScanFilterSupported = "
586                 + mNumOfOffloadedScanFilterSupported
587                 + " mOffloadedScanResultStorageBytes= "
588                 + mOffloadedScanResultStorageBytes
589                 + " mIsActivityAndEnergyReporting = "
590                 + mIsActivityAndEnergyReporting
591                 +" mVersSupported = "
592                 + mVersSupported
593                 + " mTotNumOfTrackableAdv = "
594                 + mTotNumOfTrackableAdv
595                 + " mIsExtendedScanSupported = "
596                 + mIsExtendedScanSupported
597                 + " mIsDebugLogSupported = "
598                 + mIsDebugLogSupported
599                 );
600     }
601 
onBluetoothReady()602     void onBluetoothReady() {
603         Log.d(TAG, "ScanMode =  " + mScanMode );
604         Log.d(TAG, "State =  " + getState() );
605 
606         // When BT is being turned on, all adapter properties will be sent in 1
607         // callback. At this stage, set the scan mode.
608         synchronized (mObject) {
609             if (getState() == BluetoothAdapter.STATE_TURNING_ON &&
610                     mScanMode == BluetoothAdapter.SCAN_MODE_NONE) {
611                     /* mDiscoverableTimeout is part of the
612                        adapterPropertyChangedCallback received before
613                        onBluetoothReady */
614                     if (mDiscoverableTimeout != 0)
615                       setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE);
616                     else /* if timeout == never (0) at startup */
617                       setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
618                     /* though not always required, this keeps NV up-to date on first-boot after flash */
619                     setDiscoverableTimeout(mDiscoverableTimeout);
620             }
621         }
622     }
623 
624     private boolean mBluetoothDisabling = false;
625 
onBleDisable()626     void onBleDisable() {
627         // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state.
628         // When BT disable is invoked, set the scan_mode to NONE
629         // so no incoming connections are possible
630         debugLog("onBleDisable");
631         if (getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
632            setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
633         }
634     }
635 
onBluetoothDisable()636     void onBluetoothDisable() {
637         // From STATE_ON to BLE_ON
638         // When BT disable is invoked, set the scan_mode to NONE
639         // so no incoming connections are possible
640 
641         //Set flag to indicate we are disabling. When property change of scan mode done
642         //continue with disable sequence
643         debugLog("onBluetoothDisable()");
644         mBluetoothDisabling = true;
645         if (getState() == BluetoothAdapter.STATE_TURNING_OFF) {
646             // Turn off any Device Search/Inquiry
647             mService.cancelDiscovery();
648             setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
649         }
650     }
651 
discoveryStateChangeCallback(int state)652     void discoveryStateChangeCallback(int state) {
653         infoLog("Callback:discoveryStateChangeCallback with state:" + state);
654         synchronized (mObject) {
655             Intent intent;
656             if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) {
657                 mDiscovering = false;
658                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
659                 mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
660             } else if (state == AbstractionLayer.BT_DISCOVERY_STARTED) {
661                 mDiscovering = true;
662                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
663                 mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
664             }
665         }
666     }
667 
infoLog(String msg)668     private void infoLog(String msg) {
669         if (VDBG) Log.i(TAG, msg);
670     }
671 
debugLog(String msg)672     private void debugLog(String msg) {
673         if (DBG) Log.d(TAG, msg);
674     }
675 
errorLog(String msg)676     private void errorLog(String msg) {
677         Log.e(TAG, msg);
678     }
679 }
680