• 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.BluetoothA2dp;
20 import android.bluetooth.BluetoothA2dpSink;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothAvrcpController;
23 import android.bluetooth.BluetoothDevice;
24 import android.bluetooth.BluetoothHeadset;
25 import android.bluetooth.BluetoothHeadsetClient;
26 import android.bluetooth.BluetoothInputDevice;
27 import android.bluetooth.BluetoothInputHost;
28 import android.bluetooth.BluetoothMap;
29 import android.bluetooth.BluetoothMapClient;
30 import android.bluetooth.BluetoothPan;
31 import android.bluetooth.BluetoothPbap;
32 import android.bluetooth.BluetoothPbapClient;
33 import android.bluetooth.BluetoothProfile;
34 import android.bluetooth.BluetoothSap;
35 import android.content.BroadcastReceiver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.os.ParcelUuid;
40 import android.os.UserHandle;
41 import android.util.Log;
42 import android.util.Pair;
43 
44 import com.android.bluetooth.Utils;
45 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
46 
47 import java.lang.System;
48 import java.util.HashMap;
49 import java.util.concurrent.CopyOnWriteArrayList;
50 
51 class AdapterProperties {
52     private static final boolean DBG = true;
53     private static final boolean VDBG = false;
54     private static final String TAG = "BluetoothAdapterProperties";
55 
56     private static final long DEFAULT_DISCOVERY_TIMEOUT_MS = 12800;
57     private static final int BD_ADDR_LEN = 6; // in bytes
58 
59     private volatile String mName;
60     private volatile byte[] mAddress;
61     private volatile int mBluetoothClass;
62     private volatile int mScanMode;
63     private volatile int mDiscoverableTimeout;
64     private volatile ParcelUuid[] mUuids;
65     private CopyOnWriteArrayList<BluetoothDevice> mBondedDevices = new CopyOnWriteArrayList<BluetoothDevice>();
66 
67     private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting;
68     private final HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState =
69             new HashMap<>();
70 
71     private volatile int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
72     private volatile int mState = BluetoothAdapter.STATE_OFF;
73 
74     private AdapterService mService;
75     private boolean mDiscovering;
76     private long mDiscoveryEndMs; //< Time (ms since epoch) that discovery ended or will end.
77     private RemoteDevices mRemoteDevices;
78     private BluetoothAdapter mAdapter;
79     //TODO - all hw capabilities to be exposed as a class
80     private int mNumOfAdvertisementInstancesSupported;
81     private boolean mRpaOffloadSupported;
82     private int mNumOfOffloadedIrkSupported;
83     private int mNumOfOffloadedScanFilterSupported;
84     private int mOffloadedScanResultStorageBytes;
85     private int mVersSupported;
86     private int mTotNumOfTrackableAdv;
87     private boolean mIsExtendedScanSupported;
88     private boolean mIsDebugLogSupported;
89     private boolean mIsActivityAndEnergyReporting;
90     private boolean mIsLe2MPhySupported;
91     private boolean mIsLeCodedPhySupported;
92     private boolean mIsLeExtendedAdvertisingSupported;
93     private boolean mIsLePeriodicAdvertisingSupported;
94     private int mLeMaximumAdvertisingDataLength;
95 
96     private boolean mReceiverRegistered;
97     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
98         @Override
99         public void onReceive(Context context, Intent intent) {
100             String action = intent.getAction();
101             if (action == null) {
102                 Log.w(TAG, "Received intent with null action");
103                 return;
104             }
105             switch (action) {
106                 case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
107                     sendConnectionStateChange(BluetoothProfile.HEADSET, intent);
108                     break;
109                 case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
110                     sendConnectionStateChange(BluetoothProfile.A2DP, intent);
111                     break;
112                 case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED:
113                     sendConnectionStateChange(BluetoothProfile.HEADSET_CLIENT, intent);
114                     break;
115                 case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED:
116                     sendConnectionStateChange(BluetoothProfile.A2DP_SINK, intent);
117                     break;
118                 case BluetoothInputHost.ACTION_CONNECTION_STATE_CHANGED:
119                     sendConnectionStateChange(BluetoothProfile.INPUT_HOST, intent);
120                     break;
121                 case BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED:
122                     sendConnectionStateChange(BluetoothProfile.INPUT_DEVICE, intent);
123                     break;
124                 case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED:
125                     sendConnectionStateChange(BluetoothProfile.AVRCP_CONTROLLER, intent);
126                     break;
127                 case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED:
128                     sendConnectionStateChange(BluetoothProfile.PAN, intent);
129                     break;
130                 case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED:
131                     sendConnectionStateChange(BluetoothProfile.MAP, intent);
132                     break;
133                 case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED:
134                     sendConnectionStateChange(BluetoothProfile.MAP_CLIENT, intent);
135                     break;
136                 case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED:
137                     sendConnectionStateChange(BluetoothProfile.SAP, intent);
138                     break;
139                 case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED:
140                     sendConnectionStateChange(BluetoothProfile.PBAP_CLIENT, intent);
141                     break;
142                 default:
143                     Log.w(TAG, "Received unknown intent " + intent);
144                     break;
145             }
146         }
147     };
148 
149     // Lock for all getters and setters.
150     // If finer grained locking is needer, more locks
151     // can be added here.
152     private final Object mObject = new Object();
153 
AdapterProperties(AdapterService service)154     public AdapterProperties(AdapterService service) {
155         mService = service;
156         mAdapter = BluetoothAdapter.getDefaultAdapter();
157     }
init(RemoteDevices remoteDevices)158     public void init(RemoteDevices remoteDevices) {
159         mProfileConnectionState.clear();
160         mRemoteDevices = remoteDevices;
161 
162         IntentFilter filter = new IntentFilter();
163         filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
164         filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
165         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
166         filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
167         filter.addAction(BluetoothInputHost.ACTION_CONNECTION_STATE_CHANGED);
168         filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
169         filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
170         filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
171         filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
172         filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
173         filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
174         filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
175         mService.registerReceiver(mReceiver, filter);
176         mReceiverRegistered = true;
177     }
178 
cleanup()179     public void cleanup() {
180         mRemoteDevices = null;
181         mProfileConnectionState.clear();
182         if (mReceiverRegistered) {
183             mService.unregisterReceiver(mReceiver);
184             mReceiverRegistered = false;
185         }
186         mService = null;
187         mBondedDevices.clear();
188     }
189 
190     @Override
clone()191     public Object clone() throws CloneNotSupportedException {
192         throw new CloneNotSupportedException();
193     }
194 
195     /**
196      * @return the mName
197      */
getName()198     String getName() {
199         return mName;
200     }
201 
202     /**
203      * Set the local adapter property - name
204      * @param name the name to set
205      */
setName(String name)206     boolean setName(String name) {
207         synchronized (mObject) {
208             return mService.setAdapterPropertyNative(
209                     AbstractionLayer.BT_PROPERTY_BDNAME, name.getBytes());
210         }
211     }
212 
213     /**
214      * @return the mClass
215      */
getBluetoothClass()216     int getBluetoothClass() {
217         return mBluetoothClass;
218     }
219 
220     /**
221      * @return the mScanMode
222      */
getScanMode()223     int getScanMode() {
224         return mScanMode;
225     }
226 
227     /**
228      * Set the local adapter property - scanMode
229      *
230      * @param scanMode the ScanMode to set
231      */
setScanMode(int scanMode)232     boolean setScanMode(int scanMode) {
233         synchronized (mObject) {
234             return mService.setAdapterPropertyNative(
235                     AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE, Utils.intToByteArray(scanMode));
236         }
237     }
238 
239     /**
240      * @return the mUuids
241      */
getUuids()242     ParcelUuid[] getUuids() {
243         return mUuids;
244     }
245 
246     /**
247      * @return the mAddress
248      */
getAddress()249     byte[] getAddress() {
250         return mAddress;
251     }
252 
253     /**
254      * @param mConnectionState the mConnectionState to set
255      */
setConnectionState(int mConnectionState)256     void setConnectionState(int mConnectionState) {
257         this.mConnectionState = mConnectionState;
258     }
259 
260     /**
261      * @return the mConnectionState
262      */
getConnectionState()263     int getConnectionState() {
264         return mConnectionState;
265     }
266 
267     /**
268      * @param mState the mState to set
269      */
setState(int mState)270     void setState(int mState) {
271         debugLog("Setting state to " + mState);
272         this.mState = mState;
273     }
274 
275     /**
276      * @return the mState
277      */
getState()278     int getState() {
279         return mState;
280     }
281 
282     /**
283      * @return the mNumOfAdvertisementInstancesSupported
284      */
getNumOfAdvertisementInstancesSupported()285     int getNumOfAdvertisementInstancesSupported() {
286         return mNumOfAdvertisementInstancesSupported;
287     }
288 
289     /**
290      * @return the mRpaOffloadSupported
291      */
isRpaOffloadSupported()292     boolean isRpaOffloadSupported() {
293         return mRpaOffloadSupported;
294     }
295 
296     /**
297      * @return the mNumOfOffloadedIrkSupported
298      */
getNumOfOffloadedIrkSupported()299     int getNumOfOffloadedIrkSupported() {
300         return mNumOfOffloadedIrkSupported;
301     }
302 
303     /**
304      * @return the mNumOfOffloadedScanFilterSupported
305      */
getNumOfOffloadedScanFilterSupported()306     int getNumOfOffloadedScanFilterSupported() {
307         return mNumOfOffloadedScanFilterSupported;
308     }
309 
310     /**
311      * @return the mOffloadedScanResultStorageBytes
312      */
getOffloadedScanResultStorage()313     int getOffloadedScanResultStorage() {
314         return mOffloadedScanResultStorageBytes;
315     }
316 
317     /**
318      * @return tx/rx/idle activity and energy info
319      */
isActivityAndEnergyReportingSupported()320     boolean isActivityAndEnergyReportingSupported() {
321         return mIsActivityAndEnergyReporting;
322     }
323 
324     /**
325      * @return the mIsLe2MPhySupported
326      */
isLe2MPhySupported()327     boolean isLe2MPhySupported() {
328         return mIsLe2MPhySupported;
329     }
330 
331     /**
332      * @return the mIsLeCodedPhySupported
333      */
isLeCodedPhySupported()334     boolean isLeCodedPhySupported() {
335         return mIsLeCodedPhySupported;
336     }
337 
338     /**
339      * @return the mIsLeExtendedAdvertisingSupported
340      */
isLeExtendedAdvertisingSupported()341     boolean isLeExtendedAdvertisingSupported() {
342         return mIsLeExtendedAdvertisingSupported;
343     }
344 
345     /**
346      * @return the mIsLePeriodicAdvertisingSupported
347      */
isLePeriodicAdvertisingSupported()348     boolean isLePeriodicAdvertisingSupported() {
349         return mIsLePeriodicAdvertisingSupported;
350     }
351 
352     /**
353      * @return the getLeMaximumAdvertisingDataLength
354      */
getLeMaximumAdvertisingDataLength()355     int getLeMaximumAdvertisingDataLength() {
356         return mLeMaximumAdvertisingDataLength;
357     }
358 
359     /**
360      * @return total number of trackable advertisements
361      */
getTotalNumOfTrackableAdvertisements()362     int getTotalNumOfTrackableAdvertisements() {
363         return mTotNumOfTrackableAdv;
364     }
365 
366     /**
367      * @return the mBondedDevices
368      */
getBondedDevices()369     BluetoothDevice[] getBondedDevices() {
370         BluetoothDevice[] bondedDeviceList = new BluetoothDevice[0];
371         try {
372             bondedDeviceList = mBondedDevices.toArray(bondedDeviceList);
373         } catch(ArrayStoreException ee) {
374             errorLog("Error retrieving bonded device array");
375         }
376         infoLog("getBondedDevices: length=" + bondedDeviceList.length);
377         return bondedDeviceList;
378     }
379 
380     // This function shall be invoked from BondStateMachine whenever the bond
381     // state changes.
onBondStateChanged(BluetoothDevice device, int state)382     void onBondStateChanged(BluetoothDevice device, int state)
383     {
384         if (device == null) {
385             Log.w(TAG, "onBondStateChanged, device is null");
386             return;
387         }
388         try {
389             byte[] addrByte = Utils.getByteAddress(device);
390             DeviceProperties prop = mRemoteDevices.getDeviceProperties(device);
391             if (prop == null)
392                 prop = mRemoteDevices.addDeviceProperties(addrByte);
393             prop.setBondState(state);
394 
395             if (state == BluetoothDevice.BOND_BONDED) {
396                 // add if not already in list
397                 if(!mBondedDevices.contains(device)) {
398                     debugLog("Adding bonded device:" +  device);
399                     mBondedDevices.add(device);
400                 }
401             } else if (state == BluetoothDevice.BOND_NONE) {
402                 // remove device from list
403                 if (mBondedDevices.remove(device))
404                     debugLog("Removing bonded device:" +  device);
405                 else
406                     debugLog("Failed to remove device: " + device);
407             }
408         }
409         catch(Exception ee) {
410             Log.w(TAG, "onBondStateChanged: Exception ", ee);
411         }
412     }
413 
getDiscoverableTimeout()414     int getDiscoverableTimeout() {
415         return mDiscoverableTimeout;
416     }
417 
setDiscoverableTimeout(int timeout)418     boolean setDiscoverableTimeout(int timeout) {
419         synchronized (mObject) {
420             return mService.setAdapterPropertyNative(
421                     AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT,
422                     Utils.intToByteArray(timeout));
423         }
424     }
425 
getProfileConnectionState(int profile)426     int getProfileConnectionState(int profile) {
427         synchronized (mObject) {
428             Pair<Integer, Integer> p = mProfileConnectionState.get(profile);
429             if (p != null) return p.first;
430             return BluetoothProfile.STATE_DISCONNECTED;
431         }
432     }
433 
discoveryEndMillis()434     long discoveryEndMillis() {
435         return mDiscoveryEndMs;
436     }
437 
isDiscovering()438     boolean isDiscovering() {
439         return mDiscovering;
440     }
441 
sendConnectionStateChange(int profile, Intent connIntent)442     private void sendConnectionStateChange(int profile, Intent connIntent) {
443         BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
444         int prevState = connIntent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
445         int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
446         Log.d(TAG,
447                 "PROFILE_CONNECTION_STATE_CHANGE: profile=" + profile + ", device=" + device + ", "
448                         + prevState + " -> " + state);
449         if (!isNormalStateTransition(prevState, state)) {
450             Log.w(TAG,
451                     "PROFILE_CONNECTION_STATE_CHANGE: unexpected transition for profile=" + profile
452                             + ", device=" + device + ", " + prevState + " -> " + state);
453         }
454         sendConnectionStateChange(device, profile, state, prevState);
455     }
sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)456     void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
457         if (!validateProfileConnectionState(state) ||
458                 !validateProfileConnectionState(prevState)) {
459             // Previously, an invalid state was broadcast anyway,
460             // with the invalid state converted to -1 in the intent.
461             // Better to log an error and not send an intent with
462             // invalid contents or set mAdapterConnectionState to -1.
463             errorLog("sendConnectionStateChange: invalid state transition " + prevState + " -> "
464                     + state);
465             return;
466         }
467 
468         synchronized (mObject) {
469             updateProfileConnectionState(profile, state, prevState);
470 
471             if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
472                 int newAdapterState = convertToAdapterState(state);
473                 int prevAdapterState = convertToAdapterState(prevState);
474                 setConnectionState(newAdapterState);
475 
476                 Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
477                 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
478                 intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, newAdapterState);
479                 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, prevAdapterState);
480                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
481                 Log.d(TAG,
482                         "ADAPTER_CONNECTION_STATE_CHANGE: " + device + ": " + prevAdapterState
483                                 + " -> " + newAdapterState);
484                 if (!isNormalStateTransition(prevState, state)) {
485                     Log.w(TAG,
486                             "ADAPTER_CONNECTION_STATE_CHANGE: unexpected transition for profile="
487                                     + profile + ", device=" + device + ", " + prevState + " -> "
488                                     + state);
489                 }
490                 mService.sendBroadcastAsUser(intent, UserHandle.ALL, AdapterService.BLUETOOTH_PERM);
491             }
492         }
493     }
494 
validateProfileConnectionState(int state)495     private boolean validateProfileConnectionState(int state) {
496         return (state == BluetoothProfile.STATE_DISCONNECTED ||
497                 state == BluetoothProfile.STATE_CONNECTING ||
498                 state == BluetoothProfile.STATE_CONNECTED ||
499                 state == BluetoothProfile.STATE_DISCONNECTING);
500     }
501 
convertToAdapterState(int state)502     private static int convertToAdapterState(int state) {
503         switch (state) {
504             case BluetoothProfile.STATE_DISCONNECTED:
505                 return BluetoothAdapter.STATE_DISCONNECTED;
506             case BluetoothProfile.STATE_DISCONNECTING:
507                 return BluetoothAdapter.STATE_DISCONNECTING;
508             case BluetoothProfile.STATE_CONNECTED:
509                 return BluetoothAdapter.STATE_CONNECTED;
510             case BluetoothProfile.STATE_CONNECTING:
511                 return BluetoothAdapter.STATE_CONNECTING;
512         }
513         Log.e(TAG, "convertToAdapterState, unknow state " + state);
514         return -1;
515     }
516 
isNormalStateTransition(int prevState, int nextState)517     private static boolean isNormalStateTransition(int prevState, int nextState) {
518         switch (prevState) {
519             case BluetoothProfile.STATE_DISCONNECTED:
520                 return nextState == BluetoothProfile.STATE_CONNECTING;
521             case BluetoothProfile.STATE_CONNECTED:
522                 return nextState == BluetoothProfile.STATE_DISCONNECTING;
523             case BluetoothProfile.STATE_DISCONNECTING:
524             case BluetoothProfile.STATE_CONNECTING:
525                 return (nextState == BluetoothProfile.STATE_DISCONNECTED)
526                         || (nextState == BluetoothProfile.STATE_CONNECTED);
527             default:
528                 return false;
529         }
530     }
531 
updateCountersAndCheckForConnectionStateChange(int state, int prevState)532     private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
533         switch (prevState) {
534             case BluetoothProfile.STATE_CONNECTING:
535                 if (mProfilesConnecting > 0)
536                     mProfilesConnecting--;
537                 else
538                     Log.e(TAG, "mProfilesConnecting " + mProfilesConnecting);
539                 break;
540 
541             case BluetoothProfile.STATE_CONNECTED:
542                 if (mProfilesConnected > 0)
543                     mProfilesConnected--;
544                 else
545                     Log.e(TAG, "mProfilesConnected " + mProfilesConnected);
546                 break;
547 
548             case BluetoothProfile.STATE_DISCONNECTING:
549                 if (mProfilesDisconnecting > 0)
550                     mProfilesDisconnecting--;
551                 else
552                     Log.e(TAG, "mProfilesDisconnecting " + mProfilesDisconnecting);
553                 break;
554         }
555 
556         switch (state) {
557             case BluetoothProfile.STATE_CONNECTING:
558                 mProfilesConnecting++;
559                 return (mProfilesConnected == 0 && mProfilesConnecting == 1);
560 
561             case BluetoothProfile.STATE_CONNECTED:
562                 mProfilesConnected++;
563                 return (mProfilesConnected == 1);
564 
565             case BluetoothProfile.STATE_DISCONNECTING:
566                 mProfilesDisconnecting++;
567                 return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
568 
569             case BluetoothProfile.STATE_DISCONNECTED:
570                 return (mProfilesConnected == 0 && mProfilesConnecting == 0);
571 
572             default:
573                 return true;
574         }
575     }
576 
updateProfileConnectionState(int profile, int newState, int oldState)577     private void updateProfileConnectionState(int profile, int newState, int oldState) {
578         // mProfileConnectionState is a hashmap -
579         // <Integer, Pair<Integer, Integer>>
580         // The key is the profile, the value is a pair. first element
581         // is the state and the second element is the number of devices
582         // in that state.
583         int numDev = 1;
584         int newHashState = newState;
585         boolean update = true;
586 
587         // The following conditions are considered in this function:
588         // 1. If there is no record of profile and state - update
589         // 2. If a new device's state is current hash state - increment
590         //    number of devices in the state.
591         // 3. If a state change has happened to Connected or Connecting
592         //    (if current state is not connected), update.
593         // 4. If numDevices is 1 and that device state is being updated, update
594         // 5. If numDevices is > 1 and one of the devices is changing state,
595         //    decrement numDevices but maintain oldState if it is Connected or
596         //    Connecting
597         Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
598         if (stateNumDev != null) {
599             int currHashState = stateNumDev.first;
600             numDev = stateNumDev.second;
601 
602             if (newState == currHashState) {
603                 numDev ++;
604             } else if (newState == BluetoothProfile.STATE_CONNECTED ||
605                    (newState == BluetoothProfile.STATE_CONNECTING &&
606                     currHashState != BluetoothProfile.STATE_CONNECTED)) {
607                  numDev = 1;
608             } else if (numDev == 1 && oldState == currHashState) {
609                  update = true;
610             } else if (numDev > 1 && oldState == currHashState) {
611                  numDev --;
612 
613                  if (currHashState == BluetoothProfile.STATE_CONNECTED ||
614                      currHashState == BluetoothProfile.STATE_CONNECTING) {
615                     newHashState = currHashState;
616                  }
617             } else {
618                  update = false;
619             }
620         }
621 
622         if (update) {
623             mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState,
624                     numDev));
625         }
626     }
627 
adapterPropertyChangedCallback(int[] types, byte[][] values)628     void adapterPropertyChangedCallback(int[] types, byte[][] values) {
629         Intent intent;
630         int type;
631         byte[] val;
632         for (int i = 0; i < types.length; i++) {
633             val = values[i];
634             type = types[i];
635             infoLog("adapterPropertyChangedCallback with type:" + type + " len:" + val.length);
636             synchronized (mObject) {
637                 switch (type) {
638                     case AbstractionLayer.BT_PROPERTY_BDNAME:
639                         mName = new String(val);
640                         intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
641                         intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
642                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
643                         mService.sendBroadcastAsUser(
644                                 intent, UserHandle.ALL, AdapterService.BLUETOOTH_PERM);
645                         debugLog("Name is: " + mName);
646                         break;
647                     case AbstractionLayer.BT_PROPERTY_BDADDR:
648                         mAddress = val;
649                         String address = Utils.getAddressStringFromByte(mAddress);
650                         debugLog("Address is:" + address);
651                         intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
652                         intent.putExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS, address);
653                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
654                         mService.sendBroadcastAsUser(
655                                 intent, UserHandle.ALL, AdapterService.BLUETOOTH_PERM);
656                         break;
657                     case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE:
658                         mBluetoothClass = Utils.byteArrayToInt(val, 0);
659                         debugLog("BT Class:" + mBluetoothClass);
660                         break;
661                     case AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE:
662                         int mode = Utils.byteArrayToInt(val, 0);
663                         mScanMode = AdapterService.convertScanModeFromHal(mode);
664                         intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
665                         intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode);
666                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
667                         mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
668                         debugLog("Scan Mode:" + mScanMode);
669                         if (mBluetoothDisabling) {
670                             mBluetoothDisabling=false;
671                             mService.startBluetoothDisable();
672                         }
673                         break;
674                     case AbstractionLayer.BT_PROPERTY_UUIDS:
675                         mUuids = Utils.byteArrayToUuid(val);
676                         break;
677                     case AbstractionLayer.BT_PROPERTY_ADAPTER_BONDED_DEVICES:
678                         int number = val.length/BD_ADDR_LEN;
679                         byte[] addrByte = new byte[BD_ADDR_LEN];
680                         for (int j = 0; j < number; j++) {
681                             System.arraycopy(val, j * BD_ADDR_LEN, addrByte, 0, BD_ADDR_LEN);
682                             onBondStateChanged(mAdapter.getRemoteDevice(
683                                                Utils.getAddressStringFromByte(addrByte)),
684                                                BluetoothDevice.BOND_BONDED);
685                         }
686                         break;
687                     case AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT:
688                         mDiscoverableTimeout = Utils.byteArrayToInt(val, 0);
689                         debugLog("Discoverable Timeout:" + mDiscoverableTimeout);
690                         break;
691 
692                     case AbstractionLayer.BT_PROPERTY_LOCAL_LE_FEATURES:
693                         updateFeatureSupport(val);
694                         break;
695 
696                     default:
697                         errorLog("Property change not handled in Java land:" + type);
698                 }
699             }
700         }
701     }
702 
updateFeatureSupport(byte[] val)703     private void updateFeatureSupport(byte[] val) {
704         mVersSupported = ((0xFF & ((int)val[1])) << 8)
705                             + (0xFF & ((int)val[0]));
706         mNumOfAdvertisementInstancesSupported = (0xFF & ((int)val[3]));
707         mRpaOffloadSupported = ((0xFF & ((int)val[4]))!= 0);
708         mNumOfOffloadedIrkSupported =  (0xFF & ((int)val[5]));
709         mNumOfOffloadedScanFilterSupported = (0xFF & ((int)val[6]));
710         mIsActivityAndEnergyReporting = ((0xFF & ((int)val[7])) != 0);
711         mOffloadedScanResultStorageBytes = ((0xFF & ((int)val[9])) << 8)
712                             + (0xFF & ((int)val[8]));
713         mTotNumOfTrackableAdv = ((0xFF & ((int)val[11])) << 8)
714                             + (0xFF & ((int)val[10]));
715         mIsExtendedScanSupported = ((0xFF & ((int)val[12])) != 0);
716         mIsDebugLogSupported = ((0xFF & ((int)val[13])) != 0);
717         mIsLe2MPhySupported = ((0xFF & ((int) val[14])) != 0);
718         mIsLeCodedPhySupported = ((0xFF & ((int) val[15])) != 0);
719         mIsLeExtendedAdvertisingSupported = ((0xFF & ((int) val[16])) != 0);
720         mIsLePeriodicAdvertisingSupported = ((0xFF & ((int) val[17])) != 0);
721         mLeMaximumAdvertisingDataLength =   (0xFF & ((int)val[18]))
722                                          + ((0xFF & ((int)val[19])) << 8);
723 
724         Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller"
725                 + " mNumOfAdvertisementInstancesSupported = "
726                 + mNumOfAdvertisementInstancesSupported
727                 + " mRpaOffloadSupported = " + mRpaOffloadSupported
728                 + " mNumOfOffloadedIrkSupported = "
729                 + mNumOfOffloadedIrkSupported
730                 + " mNumOfOffloadedScanFilterSupported = "
731                 + mNumOfOffloadedScanFilterSupported
732                 + " mOffloadedScanResultStorageBytes= "
733                 + mOffloadedScanResultStorageBytes
734                 + " mIsActivityAndEnergyReporting = "
735                 + mIsActivityAndEnergyReporting
736                 +" mVersSupported = "
737                 + mVersSupported
738                 + " mTotNumOfTrackableAdv = "
739                 + mTotNumOfTrackableAdv
740                 + " mIsExtendedScanSupported = "
741                 + mIsExtendedScanSupported
742                 + " mIsDebugLogSupported = "
743                 + mIsDebugLogSupported
744                 + " mIsLe2MPhySupported = "
745                 + mIsLe2MPhySupported
746                 + " mIsLeCodedPhySupported = "
747                 + mIsLeCodedPhySupported
748                 + " mIsLeExtendedAdvertisingSupported = "
749                 + mIsLeExtendedAdvertisingSupported
750                 + " mIsLePeriodicAdvertisingSupported = "
751                 + mIsLePeriodicAdvertisingSupported
752                 + " mLeMaximumAdvertisingDataLength = "
753                 + mLeMaximumAdvertisingDataLength
754                 );
755     }
756 
onBluetoothReady()757     void onBluetoothReady() {
758         debugLog("onBluetoothReady, state=" + getState() + ", ScanMode=" + mScanMode);
759 
760         synchronized (mObject) {
761             // Reset adapter and profile connection states
762             setConnectionState(BluetoothAdapter.STATE_DISCONNECTED);
763             mProfileConnectionState.clear();
764             mProfilesConnected = 0;
765             mProfilesConnecting = 0;
766             mProfilesDisconnecting = 0;
767             // When BT is being turned on, all adapter properties will be sent in 1
768             // callback. At this stage, set the scan mode.
769             if (getState() == BluetoothAdapter.STATE_TURNING_ON &&
770                     mScanMode == BluetoothAdapter.SCAN_MODE_NONE) {
771                     /* mDiscoverableTimeout is part of the
772                        adapterPropertyChangedCallback received before
773                        onBluetoothReady */
774                     if (mDiscoverableTimeout != 0)
775                       setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE);
776                     else /* if timeout == never (0) at startup */
777                       setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
778                     /* though not always required, this keeps NV up-to date on first-boot after flash */
779                     setDiscoverableTimeout(mDiscoverableTimeout);
780             }
781         }
782     }
783 
784     private boolean mBluetoothDisabling = false;
785 
onBleDisable()786     void onBleDisable() {
787         // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state.
788         // When BT disable is invoked, set the scan_mode to NONE
789         // so no incoming connections are possible
790         debugLog("onBleDisable");
791         if (getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
792            setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
793         }
794     }
795 
onBluetoothDisable()796     void onBluetoothDisable() {
797         // From STATE_ON to BLE_ON
798         // When BT disable is invoked, set the scan_mode to NONE
799         // so no incoming connections are possible
800 
801         //Set flag to indicate we are disabling. When property change of scan mode done
802         //continue with disable sequence
803         debugLog("onBluetoothDisable()");
804         mBluetoothDisabling = true;
805         if (getState() == BluetoothAdapter.STATE_TURNING_OFF) {
806             // Turn off any Device Search/Inquiry
807             mService.cancelDiscovery();
808             setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
809         }
810     }
811 
discoveryStateChangeCallback(int state)812     void discoveryStateChangeCallback(int state) {
813         infoLog("Callback:discoveryStateChangeCallback with state:" + state);
814         synchronized (mObject) {
815             Intent intent;
816             if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) {
817                 mDiscovering = false;
818                 mDiscoveryEndMs = System.currentTimeMillis();
819                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
820                 mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
821             } else if (state == AbstractionLayer.BT_DISCOVERY_STARTED) {
822                 mDiscovering = true;
823                 mDiscoveryEndMs = System.currentTimeMillis() + DEFAULT_DISCOVERY_TIMEOUT_MS;
824                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
825                 mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
826             }
827         }
828     }
829 
infoLog(String msg)830     private static void infoLog(String msg) {
831         if (VDBG) Log.i(TAG, msg);
832     }
833 
debugLog(String msg)834     private static void debugLog(String msg) {
835         if (DBG) Log.d(TAG, msg);
836     }
837 
errorLog(String msg)838     private static void errorLog(String msg) {
839         Log.e(TAG, msg);
840     }
841 }
842