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.BluetoothClass;
24 import android.bluetooth.BluetoothDevice;
25 import android.bluetooth.BluetoothHeadset;
26 import android.bluetooth.BluetoothHeadsetClient;
27 import android.bluetooth.BluetoothHearingAid;
28 import android.bluetooth.BluetoothHidDevice;
29 import android.bluetooth.BluetoothHidHost;
30 import android.bluetooth.BluetoothMap;
31 import android.bluetooth.BluetoothMapClient;
32 import android.bluetooth.BluetoothPan;
33 import android.bluetooth.BluetoothPbap;
34 import android.bluetooth.BluetoothPbapClient;
35 import android.bluetooth.BluetoothProfile;
36 import android.bluetooth.BluetoothSap;
37 import android.content.BroadcastReceiver;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.IntentFilter;
41 import android.os.ParcelUuid;
42 import android.os.SystemProperties;
43 import android.os.UserHandle;
44 import android.util.Log;
45 import android.util.Pair;
46 
47 import androidx.annotation.VisibleForTesting;
48 
49 import com.android.bluetooth.BluetoothStatsLog;
50 import com.android.bluetooth.Utils;
51 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
52 
53 import java.io.FileDescriptor;
54 import java.io.PrintWriter;
55 import java.util.HashMap;
56 import java.util.concurrent.CopyOnWriteArrayList;
57 
58 class AdapterProperties {
59     private static final boolean DBG = true;
60     private static final boolean VDBG = false;
61     private static final String TAG = "AdapterProperties";
62 
63     private static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY =
64             "persist.bluetooth.maxconnectedaudiodevices";
65     static final int MAX_CONNECTED_AUDIO_DEVICES_LOWER_BOND = 1;
66     private static final int MAX_CONNECTED_AUDIO_DEVICES_UPPER_BOUND = 5;
67     private static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY =
68             "ro.bluetooth.a2dp_offload.supported";
69     private static final String A2DP_OFFLOAD_DISABLED_PROPERTY =
70             "persist.bluetooth.a2dp_offload.disabled";
71 
72     private static final long DEFAULT_DISCOVERY_TIMEOUT_MS = 12800;
73     private static final int BD_ADDR_LEN = 6; // in bytes
74 
75     private volatile String mName;
76     private volatile byte[] mAddress;
77     private volatile BluetoothClass mBluetoothClass;
78     private volatile int mScanMode;
79     private volatile int mDiscoverableTimeout;
80     private volatile ParcelUuid[] mUuids;
81     private volatile int mLocalIOCapability = BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
82     private volatile int mLocalIOCapabilityBLE = BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
83 
84     private CopyOnWriteArrayList<BluetoothDevice> mBondedDevices =
85             new CopyOnWriteArrayList<BluetoothDevice>();
86 
87     private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting;
88     private final HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState =
89             new HashMap<>();
90 
91     private volatile int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
92     private volatile int mState = BluetoothAdapter.STATE_OFF;
93     private int mMaxConnectedAudioDevices = 1;
94     private boolean mA2dpOffloadEnabled = false;
95 
96     private AdapterService mService;
97     private boolean mDiscovering;
98     private long mDiscoveryEndMs; //< Time (ms since epoch) that discovery ended or will end.
99     private RemoteDevices mRemoteDevices;
100     private BluetoothAdapter mAdapter;
101     //TODO - all hw capabilities to be exposed as a class
102     private int mNumOfAdvertisementInstancesSupported;
103     private boolean mRpaOffloadSupported;
104     private int mNumOfOffloadedIrkSupported;
105     private int mNumOfOffloadedScanFilterSupported;
106     private int mOffloadedScanResultStorageBytes;
107     private int mVersSupported;
108     private int mTotNumOfTrackableAdv;
109     private boolean mIsExtendedScanSupported;
110     private boolean mIsDebugLogSupported;
111     private boolean mIsActivityAndEnergyReporting;
112     private boolean mIsLe2MPhySupported;
113     private boolean mIsLeCodedPhySupported;
114     private boolean mIsLeExtendedAdvertisingSupported;
115     private boolean mIsLePeriodicAdvertisingSupported;
116     private int mLeMaximumAdvertisingDataLength;
117 
118     private boolean mReceiverRegistered;
119     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
120         @Override
121         public void onReceive(Context context, Intent intent) {
122             String action = intent.getAction();
123             if (action == null) {
124                 Log.w(TAG, "Received intent with null action");
125                 return;
126             }
127             switch (action) {
128                 case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
129                     sendConnectionStateChange(BluetoothProfile.HEADSET, intent);
130                     break;
131                 case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
132                     sendConnectionStateChange(BluetoothProfile.A2DP, intent);
133                     break;
134                 case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED:
135                     sendConnectionStateChange(BluetoothProfile.HEADSET_CLIENT, intent);
136                     break;
137                 case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
138                     sendConnectionStateChange(BluetoothProfile.HEARING_AID, intent);
139                     break;
140                 case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED:
141                     sendConnectionStateChange(BluetoothProfile.A2DP_SINK, intent);
142                     break;
143                 case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED:
144                     sendConnectionStateChange(BluetoothProfile.HID_DEVICE, intent);
145                     break;
146                 case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED:
147                     sendConnectionStateChange(BluetoothProfile.HID_HOST, intent);
148                     break;
149                 case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED:
150                     sendConnectionStateChange(BluetoothProfile.AVRCP_CONTROLLER, intent);
151                     break;
152                 case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED:
153                     sendConnectionStateChange(BluetoothProfile.PAN, intent);
154                     break;
155                 case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED:
156                     sendConnectionStateChange(BluetoothProfile.MAP, intent);
157                     break;
158                 case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED:
159                     sendConnectionStateChange(BluetoothProfile.MAP_CLIENT, intent);
160                     break;
161                 case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED:
162                     sendConnectionStateChange(BluetoothProfile.SAP, intent);
163                     break;
164                 case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED:
165                     sendConnectionStateChange(BluetoothProfile.PBAP_CLIENT, intent);
166                     break;
167                 case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED:
168                     sendConnectionStateChange(BluetoothProfile.PBAP, intent);
169                     break;
170                 default:
171                     Log.w(TAG, "Received unknown intent " + intent);
172                     break;
173             }
174         }
175     };
176 
177     // Lock for all getters and setters.
178     // If finer grained locking is needer, more locks
179     // can be added here.
180     private final Object mObject = new Object();
181 
AdapterProperties(AdapterService service)182     AdapterProperties(AdapterService service) {
183         mService = service;
184         mAdapter = BluetoothAdapter.getDefaultAdapter();
185     }
186 
init(RemoteDevices remoteDevices)187     public void init(RemoteDevices remoteDevices) {
188         mProfileConnectionState.clear();
189         mRemoteDevices = remoteDevices;
190 
191         // Get default max connected audio devices from config.xml in frameworks/base/core
192         int configDefaultMaxConnectedAudioDevices = mService.getResources().getInteger(
193                 com.android.internal.R.integer.config_bluetooth_max_connected_audio_devices);
194         // Override max connected audio devices if MAX_CONNECTED_AUDIO_DEVICES_PROPERTY is set
195         int propertyOverlayedMaxConnectedAudioDevices =
196                 SystemProperties.getInt(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY,
197                         configDefaultMaxConnectedAudioDevices);
198         // Make sure the final value of max connected audio devices is within allowed range
199         mMaxConnectedAudioDevices = Math.min(Math.max(propertyOverlayedMaxConnectedAudioDevices,
200                 MAX_CONNECTED_AUDIO_DEVICES_LOWER_BOND), MAX_CONNECTED_AUDIO_DEVICES_UPPER_BOUND);
201         Log.i(TAG, "init(), maxConnectedAudioDevices, default="
202                 + configDefaultMaxConnectedAudioDevices + ", propertyOverlayed="
203                 + propertyOverlayedMaxConnectedAudioDevices + ", finalValue="
204                 + mMaxConnectedAudioDevices);
205 
206         mA2dpOffloadEnabled =
207                 SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false)
208                 && !SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
209 
210         IntentFilter filter = new IntentFilter();
211         filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
212         filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
213         filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
214         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
215         filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
216         filter.addAction(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
217         filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
218         filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
219         filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
220         filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
221         filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
222         filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
223         filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
224         mService.registerReceiver(mReceiver, filter);
225         mReceiverRegistered = true;
226     }
227 
cleanup()228     public void cleanup() {
229         mRemoteDevices = null;
230         mProfileConnectionState.clear();
231         if (mReceiverRegistered) {
232             mService.unregisterReceiver(mReceiver);
233             mReceiverRegistered = false;
234         }
235         mService = null;
236         mBondedDevices.clear();
237     }
238 
239     @Override
clone()240     public Object clone() throws CloneNotSupportedException {
241         throw new CloneNotSupportedException();
242     }
243 
244     /**
245      * @return the mName
246      */
getName()247     String getName() {
248         return mName;
249     }
250 
251     /**
252      * Set the local adapter property - name
253      * @param name the name to set
254      */
setName(String name)255     boolean setName(String name) {
256         synchronized (mObject) {
257             return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME,
258                     name.getBytes());
259         }
260     }
261 
262     /**
263      * Set the Bluetooth Class of Device (CoD) of the adapter.
264      *
265      * <p>Bluetooth stack stores some adapter properties in native BT stack storage and some in the
266      * Java Android stack. Bluetooth CoD is stored in the Android layer through
267      * {@link android.provider.Settings.Global#BLUETOOTH_CLASS_OF_DEVICE}.
268      *
269      * <p>Due to this, the getAdapterPropertyNative and adapterPropertyChangedCallback methods don't
270      * actually update mBluetoothClass. Hence, we update the field mBluetoothClass every time we
271      * successfully update BluetoothClass.
272      *
273      * @param bluetoothClass BluetoothClass of the device
274      */
setBluetoothClass(BluetoothClass bluetoothClass)275     boolean setBluetoothClass(BluetoothClass bluetoothClass) {
276         synchronized (mObject) {
277             boolean result =
278                     mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE,
279                             bluetoothClass.getClassOfDeviceBytes());
280 
281             if (result) {
282                 mBluetoothClass = bluetoothClass;
283             }
284 
285             return result;
286         }
287     }
288 
289     /**
290      * @return the BluetoothClass of the Bluetooth adapter.
291      */
getBluetoothClass()292     BluetoothClass getBluetoothClass() {
293         synchronized (mObject) {
294             return mBluetoothClass;
295         }
296     }
297 
setIoCapability(int capability)298     boolean setIoCapability(int capability) {
299         synchronized (mObject) {
300             boolean result = mService.setAdapterPropertyNative(
301                     AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS, Utils.intToByteArray(capability));
302 
303             if (result) {
304                 mLocalIOCapability = capability;
305             }
306 
307             return result;
308         }
309     }
310 
getIoCapability()311     int getIoCapability() {
312         synchronized (mObject) {
313             return mLocalIOCapability;
314         }
315     }
316 
setLeIoCapability(int capability)317     boolean setLeIoCapability(int capability) {
318         synchronized (mObject) {
319             boolean result = mService.setAdapterPropertyNative(
320                     AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS_BLE,
321                     Utils.intToByteArray(capability));
322 
323             if (result) {
324                 mLocalIOCapabilityBLE = capability;
325             }
326 
327             return result;
328         }
329     }
330 
getLeIoCapability()331     int getLeIoCapability() {
332         synchronized (mObject) {
333             return mLocalIOCapabilityBLE;
334         }
335     }
336 
337     /**
338      * @return the mScanMode
339      */
getScanMode()340     int getScanMode() {
341         return mScanMode;
342     }
343 
344     /**
345      * Set the local adapter property - scanMode
346      *
347      * @param scanMode the ScanMode to set
348      */
setScanMode(int scanMode)349     boolean setScanMode(int scanMode) {
350         synchronized (mObject) {
351             return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE,
352                     Utils.intToByteArray(scanMode));
353         }
354     }
355 
356     /**
357      * @return the mUuids
358      */
getUuids()359     ParcelUuid[] getUuids() {
360         return mUuids;
361     }
362 
363     /**
364      * @return the mAddress
365      */
getAddress()366     byte[] getAddress() {
367         return mAddress;
368     }
369 
370     /**
371      * @param connectionState the mConnectionState to set
372      */
setConnectionState(int connectionState)373     void setConnectionState(int connectionState) {
374         mConnectionState = connectionState;
375     }
376 
377     /**
378      * @return the mConnectionState
379      */
getConnectionState()380     int getConnectionState() {
381         return mConnectionState;
382     }
383 
384     /**
385      * @param mState the mState to set
386      */
setState(int state)387     void setState(int state) {
388         debugLog("Setting state to " + BluetoothAdapter.nameForState(state));
389         mState = state;
390     }
391 
392     /**
393      * @return the mState
394      */
getState()395     int getState() {
396         return mState;
397     }
398 
399     /**
400      * @return the mNumOfAdvertisementInstancesSupported
401      */
getNumOfAdvertisementInstancesSupported()402     int getNumOfAdvertisementInstancesSupported() {
403         return mNumOfAdvertisementInstancesSupported;
404     }
405 
406     /**
407      * @return the mRpaOffloadSupported
408      */
isRpaOffloadSupported()409     boolean isRpaOffloadSupported() {
410         return mRpaOffloadSupported;
411     }
412 
413     /**
414      * @return the mNumOfOffloadedIrkSupported
415      */
getNumOfOffloadedIrkSupported()416     int getNumOfOffloadedIrkSupported() {
417         return mNumOfOffloadedIrkSupported;
418     }
419 
420     /**
421      * @return the mNumOfOffloadedScanFilterSupported
422      */
getNumOfOffloadedScanFilterSupported()423     int getNumOfOffloadedScanFilterSupported() {
424         return mNumOfOffloadedScanFilterSupported;
425     }
426 
427     /**
428      * @return the mOffloadedScanResultStorageBytes
429      */
getOffloadedScanResultStorage()430     int getOffloadedScanResultStorage() {
431         return mOffloadedScanResultStorageBytes;
432     }
433 
434     /**
435      * @return tx/rx/idle activity and energy info
436      */
isActivityAndEnergyReportingSupported()437     boolean isActivityAndEnergyReportingSupported() {
438         return mIsActivityAndEnergyReporting;
439     }
440 
441     /**
442      * @return the mIsLe2MPhySupported
443      */
isLe2MPhySupported()444     boolean isLe2MPhySupported() {
445         return mIsLe2MPhySupported;
446     }
447 
448     /**
449      * @return the mIsLeCodedPhySupported
450      */
isLeCodedPhySupported()451     boolean isLeCodedPhySupported() {
452         return mIsLeCodedPhySupported;
453     }
454 
455     /**
456      * @return the mIsLeExtendedAdvertisingSupported
457      */
isLeExtendedAdvertisingSupported()458     boolean isLeExtendedAdvertisingSupported() {
459         return mIsLeExtendedAdvertisingSupported;
460     }
461 
462     /**
463      * @return the mIsLePeriodicAdvertisingSupported
464      */
isLePeriodicAdvertisingSupported()465     boolean isLePeriodicAdvertisingSupported() {
466         return mIsLePeriodicAdvertisingSupported;
467     }
468 
469     /**
470      * @return the getLeMaximumAdvertisingDataLength
471      */
getLeMaximumAdvertisingDataLength()472     int getLeMaximumAdvertisingDataLength() {
473         return mLeMaximumAdvertisingDataLength;
474     }
475 
476     /**
477      * @return total number of trackable advertisements
478      */
getTotalNumOfTrackableAdvertisements()479     int getTotalNumOfTrackableAdvertisements() {
480         return mTotNumOfTrackableAdv;
481     }
482 
483     /**
484      * @return the maximum number of connected audio devices
485      */
getMaxConnectedAudioDevices()486     int getMaxConnectedAudioDevices() {
487         return mMaxConnectedAudioDevices;
488     }
489 
490     /**
491      * @return A2DP offload support
492      */
isA2dpOffloadEnabled()493     boolean isA2dpOffloadEnabled() {
494         return mA2dpOffloadEnabled;
495     }
496 
497     /**
498      * @return the mBondedDevices
499      */
getBondedDevices()500     BluetoothDevice[] getBondedDevices() {
501         BluetoothDevice[] bondedDeviceList = new BluetoothDevice[0];
502         try {
503             bondedDeviceList = mBondedDevices.toArray(bondedDeviceList);
504         } catch (ArrayStoreException ee) {
505             errorLog("Error retrieving bonded device array");
506         }
507         infoLog("getBondedDevices: length=" + bondedDeviceList.length);
508         return bondedDeviceList;
509     }
510 
511     // This function shall be invoked from BondStateMachine whenever the bond
512     // state changes.
513     @VisibleForTesting
onBondStateChanged(BluetoothDevice device, int state)514     void onBondStateChanged(BluetoothDevice device, int state) {
515         if (device == null) {
516             Log.w(TAG, "onBondStateChanged, device is null");
517             return;
518         }
519         try {
520             byte[] addrByte = Utils.getByteAddress(device);
521             DeviceProperties prop = mRemoteDevices.getDeviceProperties(device);
522             if (prop == null) {
523                 prop = mRemoteDevices.addDeviceProperties(addrByte);
524             }
525             prop.setBondState(state);
526 
527             if (state == BluetoothDevice.BOND_BONDED) {
528                 // add if not already in list
529                 if (!mBondedDevices.contains(device)) {
530                     debugLog("Adding bonded device:" + device);
531                     mBondedDevices.add(device);
532                 }
533             } else if (state == BluetoothDevice.BOND_NONE) {
534                 // remove device from list
535                 if (mBondedDevices.remove(device)) {
536                     debugLog("Removing bonded device:" + device);
537                 } else {
538                     debugLog("Failed to remove device: " + device);
539                 }
540             }
541         } catch (Exception ee) {
542             Log.w(TAG, "onBondStateChanged: Exception ", ee);
543         }
544     }
545 
getDiscoverableTimeout()546     int getDiscoverableTimeout() {
547         return mDiscoverableTimeout;
548     }
549 
setDiscoverableTimeout(int timeout)550     boolean setDiscoverableTimeout(int timeout) {
551         synchronized (mObject) {
552             return mService.setAdapterPropertyNative(
553                     AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT,
554                     Utils.intToByteArray(timeout));
555         }
556     }
557 
getProfileConnectionState(int profile)558     int getProfileConnectionState(int profile) {
559         synchronized (mObject) {
560             Pair<Integer, Integer> p = mProfileConnectionState.get(profile);
561             if (p != null) {
562                 return p.first;
563             }
564             return BluetoothProfile.STATE_DISCONNECTED;
565         }
566     }
567 
discoveryEndMillis()568     long discoveryEndMillis() {
569         return mDiscoveryEndMs;
570     }
571 
isDiscovering()572     boolean isDiscovering() {
573         return mDiscovering;
574     }
575 
sendConnectionStateChange(int profile, Intent connIntent)576     private void sendConnectionStateChange(int profile, Intent connIntent) {
577         BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
578         int prevState = connIntent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
579         int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
580         Log.d(TAG,
581                 "PROFILE_CONNECTION_STATE_CHANGE: profile=" + profile + ", device=" + device + ", "
582                         + prevState + " -> " + state);
583         BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, state,
584                 0 /* deprecated */, profile, mService.obfuscateAddress(device),
585                 mService.getMetricId(device));
586 
587         if (!isNormalStateTransition(prevState, state)) {
588             Log.w(TAG,
589                     "PROFILE_CONNECTION_STATE_CHANGE: unexpected transition for profile=" + profile
590                             + ", device=" + device + ", " + prevState + " -> " + state);
591         }
592         sendConnectionStateChange(device, profile, state, prevState);
593     }
594 
sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)595     void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
596         if (!validateProfileConnectionState(state) || !validateProfileConnectionState(prevState)) {
597             // Previously, an invalid state was broadcast anyway,
598             // with the invalid state converted to -1 in the intent.
599             // Better to log an error and not send an intent with
600             // invalid contents or set mAdapterConnectionState to -1.
601             errorLog("sendConnectionStateChange: invalid state transition " + prevState + " -> "
602                     + state);
603             return;
604         }
605 
606         synchronized (mObject) {
607             updateProfileConnectionState(profile, state, prevState);
608 
609             if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
610                 int newAdapterState = convertToAdapterState(state);
611                 int prevAdapterState = convertToAdapterState(prevState);
612                 setConnectionState(newAdapterState);
613 
614                 Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
615                 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
616                 intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, newAdapterState);
617                 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, prevAdapterState);
618                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
619                 Log.d(TAG, "ADAPTER_CONNECTION_STATE_CHANGE: " + device + ": " + prevAdapterState
620                         + " -> " + newAdapterState);
621                 if (!isNormalStateTransition(prevState, state)) {
622                     Log.w(TAG, "ADAPTER_CONNECTION_STATE_CHANGE: unexpected transition for profile="
623                             + profile + ", device=" + device + ", " + prevState + " -> " + state);
624                 }
625                 mService.sendBroadcastAsUser(intent, UserHandle.ALL, AdapterService.BLUETOOTH_PERM);
626             }
627         }
628     }
629 
validateProfileConnectionState(int state)630     private boolean validateProfileConnectionState(int state) {
631         return (state == BluetoothProfile.STATE_DISCONNECTED
632                 || state == BluetoothProfile.STATE_CONNECTING
633                 || state == BluetoothProfile.STATE_CONNECTED
634                 || state == BluetoothProfile.STATE_DISCONNECTING);
635     }
636 
convertToAdapterState(int state)637     private static int convertToAdapterState(int state) {
638         switch (state) {
639             case BluetoothProfile.STATE_DISCONNECTED:
640                 return BluetoothAdapter.STATE_DISCONNECTED;
641             case BluetoothProfile.STATE_DISCONNECTING:
642                 return BluetoothAdapter.STATE_DISCONNECTING;
643             case BluetoothProfile.STATE_CONNECTED:
644                 return BluetoothAdapter.STATE_CONNECTED;
645             case BluetoothProfile.STATE_CONNECTING:
646                 return BluetoothAdapter.STATE_CONNECTING;
647         }
648         Log.e(TAG, "convertToAdapterState, unknow state " + state);
649         return -1;
650     }
651 
isNormalStateTransition(int prevState, int nextState)652     private static boolean isNormalStateTransition(int prevState, int nextState) {
653         switch (prevState) {
654             case BluetoothProfile.STATE_DISCONNECTED:
655                 return nextState == BluetoothProfile.STATE_CONNECTING;
656             case BluetoothProfile.STATE_CONNECTED:
657                 return nextState == BluetoothProfile.STATE_DISCONNECTING;
658             case BluetoothProfile.STATE_DISCONNECTING:
659             case BluetoothProfile.STATE_CONNECTING:
660                 return (nextState == BluetoothProfile.STATE_DISCONNECTED) || (nextState
661                         == BluetoothProfile.STATE_CONNECTED);
662             default:
663                 return false;
664         }
665     }
666 
updateCountersAndCheckForConnectionStateChange(int state, int prevState)667     private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
668         switch (prevState) {
669             case BluetoothProfile.STATE_CONNECTING:
670                 if (mProfilesConnecting > 0) {
671                     mProfilesConnecting--;
672                 } else {
673                     Log.e(TAG, "mProfilesConnecting " + mProfilesConnecting);
674                     throw new IllegalStateException(
675                             "Invalid state transition, " + prevState + " -> " + state);
676                 }
677                 break;
678 
679             case BluetoothProfile.STATE_CONNECTED:
680                 if (mProfilesConnected > 0) {
681                     mProfilesConnected--;
682                 } else {
683                     Log.e(TAG, "mProfilesConnected " + mProfilesConnected);
684                     throw new IllegalStateException(
685                             "Invalid state transition, " + prevState + " -> " + state);
686                 }
687                 break;
688 
689             case BluetoothProfile.STATE_DISCONNECTING:
690                 if (mProfilesDisconnecting > 0) {
691                     mProfilesDisconnecting--;
692                 } else {
693                     Log.e(TAG, "mProfilesDisconnecting " + mProfilesDisconnecting);
694                     throw new IllegalStateException(
695                             "Invalid state transition, " + prevState + " -> " + state);
696                 }
697                 break;
698         }
699 
700         switch (state) {
701             case BluetoothProfile.STATE_CONNECTING:
702                 mProfilesConnecting++;
703                 return (mProfilesConnected == 0 && mProfilesConnecting == 1);
704 
705             case BluetoothProfile.STATE_CONNECTED:
706                 mProfilesConnected++;
707                 return (mProfilesConnected == 1);
708 
709             case BluetoothProfile.STATE_DISCONNECTING:
710                 mProfilesDisconnecting++;
711                 return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
712 
713             case BluetoothProfile.STATE_DISCONNECTED:
714                 return (mProfilesConnected == 0 && mProfilesConnecting == 0);
715 
716             default:
717                 return true;
718         }
719     }
720 
updateProfileConnectionState(int profile, int newState, int oldState)721     private void updateProfileConnectionState(int profile, int newState, int oldState) {
722         // mProfileConnectionState is a hashmap -
723         // <Integer, Pair<Integer, Integer>>
724         // The key is the profile, the value is a pair. first element
725         // is the state and the second element is the number of devices
726         // in that state.
727         int numDev = 1;
728         int newHashState = newState;
729         boolean update = true;
730 
731         // The following conditions are considered in this function:
732         // 1. If there is no record of profile and state - update
733         // 2. If a new device's state is current hash state - increment
734         //    number of devices in the state.
735         // 3. If a state change has happened to Connected or Connecting
736         //    (if current state is not connected), update.
737         // 4. If numDevices is 1 and that device state is being updated, update
738         // 5. If numDevices is > 1 and one of the devices is changing state,
739         //    decrement numDevices but maintain oldState if it is Connected or
740         //    Connecting
741         Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
742         if (stateNumDev != null) {
743             int currHashState = stateNumDev.first;
744             numDev = stateNumDev.second;
745 
746             if (newState == currHashState) {
747                 numDev++;
748             } else if (newState == BluetoothProfile.STATE_CONNECTED || (
749                     newState == BluetoothProfile.STATE_CONNECTING
750                             && currHashState != BluetoothProfile.STATE_CONNECTED)) {
751                 numDev = 1;
752             } else if (numDev == 1 && oldState == currHashState) {
753                 update = true;
754             } else if (numDev > 1 && oldState == currHashState) {
755                 numDev--;
756 
757                 if (currHashState == BluetoothProfile.STATE_CONNECTED
758                         || currHashState == BluetoothProfile.STATE_CONNECTING) {
759                     newHashState = currHashState;
760                 }
761             } else {
762                 update = false;
763             }
764         }
765 
766         if (update) {
767             mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState, numDev));
768         }
769     }
770 
adapterPropertyChangedCallback(int[] types, byte[][] values)771     void adapterPropertyChangedCallback(int[] types, byte[][] values) {
772         Intent intent;
773         int type;
774         byte[] val;
775         for (int i = 0; i < types.length; i++) {
776             val = values[i];
777             type = types[i];
778             infoLog("adapterPropertyChangedCallback with type:" + type + " len:" + val.length);
779             synchronized (mObject) {
780                 switch (type) {
781                     case AbstractionLayer.BT_PROPERTY_BDNAME:
782                         mName = new String(val);
783                         intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
784                         intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
785                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
786                         mService.sendBroadcastAsUser(intent, UserHandle.ALL,
787                                 AdapterService.BLUETOOTH_PERM);
788                         debugLog("Name is: " + mName);
789                         break;
790                     case AbstractionLayer.BT_PROPERTY_BDADDR:
791                         mAddress = val;
792                         String address = Utils.getAddressStringFromByte(mAddress);
793                         debugLog("Address is:" + address);
794                         intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
795                         intent.putExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS, address);
796                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
797                         mService.sendBroadcastAsUser(intent, UserHandle.ALL,
798                                 AdapterService.BLUETOOTH_PERM);
799                         break;
800                     case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE:
801                         if (val == null || val.length != 3) {
802                             debugLog("Invalid BT CoD value from stack.");
803                             return;
804                         }
805                         int bluetoothClass =
806                                 ((int) val[0] << 16) + ((int) val[1] << 8) + (int) val[2];
807                         if (bluetoothClass != 0) {
808                             mBluetoothClass = new BluetoothClass(bluetoothClass);
809                         }
810                         debugLog("BT Class:" + mBluetoothClass);
811                         break;
812                     case AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE:
813                         int mode = Utils.byteArrayToInt(val, 0);
814                         mScanMode = AdapterService.convertScanModeFromHal(mode);
815                         intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
816                         intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode);
817                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
818                         mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
819                         debugLog("Scan Mode:" + mScanMode);
820                         break;
821                     case AbstractionLayer.BT_PROPERTY_UUIDS:
822                         mUuids = Utils.byteArrayToUuid(val);
823                         break;
824                     case AbstractionLayer.BT_PROPERTY_ADAPTER_BONDED_DEVICES:
825                         int number = val.length / BD_ADDR_LEN;
826                         byte[] addrByte = new byte[BD_ADDR_LEN];
827                         for (int j = 0; j < number; j++) {
828                             System.arraycopy(val, j * BD_ADDR_LEN, addrByte, 0, BD_ADDR_LEN);
829                             onBondStateChanged(mAdapter.getRemoteDevice(
830                                     Utils.getAddressStringFromByte(addrByte)),
831                                     BluetoothDevice.BOND_BONDED);
832                         }
833                         break;
834                     case AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT:
835                         mDiscoverableTimeout = Utils.byteArrayToInt(val, 0);
836                         debugLog("Discoverable Timeout:" + mDiscoverableTimeout);
837                         break;
838 
839                     case AbstractionLayer.BT_PROPERTY_LOCAL_LE_FEATURES:
840                         updateFeatureSupport(val);
841                         break;
842 
843                     case AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS:
844                         mLocalIOCapability = Utils.byteArrayToInt(val);
845                         debugLog("mLocalIOCapability set to " + mLocalIOCapability);
846                         break;
847 
848                     case AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS_BLE:
849                         mLocalIOCapabilityBLE = Utils.byteArrayToInt(val);
850                         debugLog("mLocalIOCapabilityBLE set to " + mLocalIOCapabilityBLE);
851                         break;
852 
853                     default:
854                         errorLog("Property change not handled in Java land:" + type);
855                 }
856             }
857         }
858     }
859 
updateFeatureSupport(byte[] val)860     private void updateFeatureSupport(byte[] val) {
861         mVersSupported = ((0xFF & ((int) val[1])) << 8) + (0xFF & ((int) val[0]));
862         mNumOfAdvertisementInstancesSupported = (0xFF & ((int) val[3]));
863         mRpaOffloadSupported = ((0xFF & ((int) val[4])) != 0);
864         mNumOfOffloadedIrkSupported = (0xFF & ((int) val[5]));
865         mNumOfOffloadedScanFilterSupported = (0xFF & ((int) val[6]));
866         mIsActivityAndEnergyReporting = ((0xFF & ((int) val[7])) != 0);
867         mOffloadedScanResultStorageBytes = ((0xFF & ((int) val[9])) << 8) + (0xFF & ((int) val[8]));
868         mTotNumOfTrackableAdv = ((0xFF & ((int) val[11])) << 8) + (0xFF & ((int) val[10]));
869         mIsExtendedScanSupported = ((0xFF & ((int) val[12])) != 0);
870         mIsDebugLogSupported = ((0xFF & ((int) val[13])) != 0);
871         mIsLe2MPhySupported = ((0xFF & ((int) val[14])) != 0);
872         mIsLeCodedPhySupported = ((0xFF & ((int) val[15])) != 0);
873         mIsLeExtendedAdvertisingSupported = ((0xFF & ((int) val[16])) != 0);
874         mIsLePeriodicAdvertisingSupported = ((0xFF & ((int) val[17])) != 0);
875         mLeMaximumAdvertisingDataLength =
876                 (0xFF & ((int) val[18])) + ((0xFF & ((int) val[19])) << 8);
877 
878         Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller"
879                 + " mNumOfAdvertisementInstancesSupported = "
880                 + mNumOfAdvertisementInstancesSupported + " mRpaOffloadSupported = "
881                 + mRpaOffloadSupported + " mNumOfOffloadedIrkSupported = "
882                 + mNumOfOffloadedIrkSupported + " mNumOfOffloadedScanFilterSupported = "
883                 + mNumOfOffloadedScanFilterSupported + " mOffloadedScanResultStorageBytes= "
884                 + mOffloadedScanResultStorageBytes + " mIsActivityAndEnergyReporting = "
885                 + mIsActivityAndEnergyReporting + " mVersSupported = " + mVersSupported
886                 + " mTotNumOfTrackableAdv = " + mTotNumOfTrackableAdv
887                 + " mIsExtendedScanSupported = " + mIsExtendedScanSupported
888                 + " mIsDebugLogSupported = " + mIsDebugLogSupported + " mIsLe2MPhySupported = "
889                 + mIsLe2MPhySupported + " mIsLeCodedPhySupported = " + mIsLeCodedPhySupported
890                 + " mIsLeExtendedAdvertisingSupported = " + mIsLeExtendedAdvertisingSupported
891                 + " mIsLePeriodicAdvertisingSupported = " + mIsLePeriodicAdvertisingSupported
892                 + " mLeMaximumAdvertisingDataLength = " + mLeMaximumAdvertisingDataLength);
893     }
894 
onBluetoothReady()895     void onBluetoothReady() {
896         debugLog("onBluetoothReady, state=" + BluetoothAdapter.nameForState(getState())
897                 + ", ScanMode=" + mScanMode);
898 
899         synchronized (mObject) {
900             // Reset adapter and profile connection states
901             setConnectionState(BluetoothAdapter.STATE_DISCONNECTED);
902             mProfileConnectionState.clear();
903             mProfilesConnected = 0;
904             mProfilesConnecting = 0;
905             mProfilesDisconnecting = 0;
906             // adapterPropertyChangedCallback has already been received.  Set the scan mode.
907             setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE);
908             // This keeps NV up-to date on first-boot after flash.
909             setDiscoverableTimeout(mDiscoverableTimeout);
910         }
911     }
912 
onBleDisable()913     void onBleDisable() {
914         // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state.
915         debugLog("onBleDisable");
916         // Set the scan_mode to NONE (no incoming connections).
917         setScanMode(AbstractionLayer.BT_SCAN_MODE_NONE);
918     }
919 
discoveryStateChangeCallback(int state)920     void discoveryStateChangeCallback(int state) {
921         infoLog("Callback:discoveryStateChangeCallback with state:" + state);
922         synchronized (mObject) {
923             Intent intent;
924             if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) {
925                 mDiscovering = false;
926                 mService.clearDiscoveringPackages();
927                 mDiscoveryEndMs = System.currentTimeMillis();
928                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
929                 mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
930             } else if (state == AbstractionLayer.BT_DISCOVERY_STARTED) {
931                 mDiscovering = true;
932                 mDiscoveryEndMs = System.currentTimeMillis() + DEFAULT_DISCOVERY_TIMEOUT_MS;
933                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
934                 mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
935             }
936         }
937     }
938 
dump(FileDescriptor fd, PrintWriter writer, String[] args)939     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
940         writer.println(TAG);
941         writer.println("  " + "Name: " + getName());
942         writer.println("  " + "Address: " + Utils.getAddressStringFromByte(mAddress));
943         writer.println("  " + "BluetoothClass: " + getBluetoothClass());
944         writer.println("  " + "ScanMode: " + dumpScanMode(getScanMode()));
945         writer.println("  " + "ConnectionState: " + dumpConnectionState(getConnectionState()));
946         writer.println("  " + "State: " + BluetoothAdapter.nameForState(getState()));
947         writer.println("  " + "MaxConnectedAudioDevices: " + getMaxConnectedAudioDevices());
948         writer.println("  " + "A2dpOffloadEnabled: " + mA2dpOffloadEnabled);
949         writer.println("  " + "Discovering: " + mDiscovering);
950         writer.println("  " + "DiscoveryEndMs: " + mDiscoveryEndMs);
951 
952         writer.println("  " + "Bonded devices:");
953         for (BluetoothDevice device : mBondedDevices) {
954             writer.println(
955                     "    " + device.getAddress() + " [" + dumpDeviceType(device.getType()) + "] "
956                             + device.getName());
957         }
958     }
959 
dumpDeviceType(int deviceType)960     private String dumpDeviceType(int deviceType) {
961         switch (deviceType) {
962             case BluetoothDevice.DEVICE_TYPE_UNKNOWN:
963                 return " ???? ";
964             case BluetoothDevice.DEVICE_TYPE_CLASSIC:
965                 return "BR/EDR";
966             case BluetoothDevice.DEVICE_TYPE_LE:
967                 return "  LE  ";
968             case BluetoothDevice.DEVICE_TYPE_DUAL:
969                 return " DUAL ";
970             default:
971                 return "Invalid device type: " + deviceType;
972         }
973     }
974 
dumpConnectionState(int state)975     private String dumpConnectionState(int state) {
976         switch (state) {
977             case BluetoothAdapter.STATE_DISCONNECTED:
978                 return "STATE_DISCONNECTED";
979             case BluetoothAdapter.STATE_DISCONNECTING:
980                 return "STATE_DISCONNECTING";
981             case BluetoothAdapter.STATE_CONNECTING:
982                 return "STATE_CONNECTING";
983             case BluetoothAdapter.STATE_CONNECTED:
984                 return "STATE_CONNECTED";
985             default:
986                 return "Unknown Connection State " + state;
987         }
988     }
989 
dumpScanMode(int scanMode)990     private String dumpScanMode(int scanMode) {
991         switch (scanMode) {
992             case BluetoothAdapter.SCAN_MODE_NONE:
993                 return "SCAN_MODE_NONE";
994             case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
995                 return "SCAN_MODE_CONNECTABLE";
996             case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
997                 return "SCAN_MODE_CONNECTABLE_DISCOVERABLE";
998             default:
999                 return "Unknown Scan Mode " + scanMode;
1000         }
1001     }
1002 
infoLog(String msg)1003     private static void infoLog(String msg) {
1004         if (VDBG) {
1005             Log.i(TAG, msg);
1006         }
1007     }
1008 
debugLog(String msg)1009     private static void debugLog(String msg) {
1010         if (DBG) {
1011             Log.d(TAG, msg);
1012         }
1013     }
1014 
errorLog(String msg)1015     private static void errorLog(String msg) {
1016         Log.e(TAG, msg);
1017     }
1018 }
1019