1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  * Copyright (C) 2016-2017 The Linux Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.bluetooth.btservice;
19 
20 import static android.Manifest.permission.BLUETOOTH_CONNECT;
21 import static android.Manifest.permission.BLUETOOTH_SCAN;
22 
23 import android.annotation.NonNull;
24 import android.annotation.RequiresPermission;
25 import android.app.BroadcastOptions;
26 import android.bluetooth.BluetoothA2dp;
27 import android.bluetooth.BluetoothA2dpSink;
28 import android.bluetooth.BluetoothAdapter;
29 import android.bluetooth.BluetoothAvrcpController;
30 import android.bluetooth.BluetoothClass;
31 import android.bluetooth.BluetoothDevice;
32 import android.bluetooth.BluetoothHeadset;
33 import android.bluetooth.BluetoothHeadsetClient;
34 import android.bluetooth.BluetoothHearingAid;
35 import android.bluetooth.BluetoothHidDevice;
36 import android.bluetooth.BluetoothHidHost;
37 import android.bluetooth.BluetoothLeAudio;
38 import android.bluetooth.BluetoothMap;
39 import android.bluetooth.BluetoothMapClient;
40 import android.bluetooth.BluetoothPan;
41 import android.bluetooth.BluetoothPbap;
42 import android.bluetooth.BluetoothPbapClient;
43 import android.bluetooth.BluetoothProfile;
44 import android.bluetooth.BluetoothSap;
45 import android.bluetooth.BufferConstraint;
46 import android.bluetooth.BufferConstraints;
47 import android.content.BroadcastReceiver;
48 import android.content.Context;
49 import android.content.Intent;
50 import android.content.IntentFilter;
51 import android.os.Bundle;
52 import android.os.ParcelUuid;
53 import android.os.SystemProperties;
54 import android.os.UserHandle;
55 import android.util.Log;
56 import android.util.Pair;
57 
58 import androidx.annotation.VisibleForTesting;
59 
60 import com.android.bluetooth.BluetoothStatsLog;
61 import com.android.bluetooth.Utils;
62 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
63 import com.android.bluetooth.flags.Flags;
64 import com.android.modules.utils.build.SdkLevel;
65 
66 import com.google.common.collect.EvictingQueue;
67 
68 import java.io.FileDescriptor;
69 import java.io.PrintWriter;
70 import java.util.ArrayList;
71 import java.util.HashMap;
72 import java.util.List;
73 import java.util.concurrent.CompletableFuture;
74 import java.util.concurrent.CopyOnWriteArrayList;
75 
76 class AdapterProperties {
77     private static final String TAG = "AdapterProperties";
78 
79     private static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY =
80             "persist.bluetooth.maxconnectedaudiodevices";
81     private static final int MAX_CONNECTED_AUDIO_DEVICES_LOWER_BOUND = 1;
82     private static final int MAX_CONNECTED_AUDIO_DEVICES_UPPER_BOUND = 5;
83     private static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY =
84             "ro.bluetooth.a2dp_offload.supported";
85     private static final String A2DP_OFFLOAD_DISABLED_PROPERTY =
86             "persist.bluetooth.a2dp_offload.disabled";
87 
88     private static final long DEFAULT_DISCOVERY_TIMEOUT_MS = 12800;
89     @VisibleForTesting static final int BLUETOOTH_NAME_MAX_LENGTH_BYTES = 248;
90     private static final int BD_ADDR_LEN = 6; // in bytes
91     private static final int SYSTEM_CONNECTION_LATENCY_METRIC = 65536;
92 
93     private volatile String mName;
94     private volatile byte[] mAddress;
95     private volatile BluetoothClass mBluetoothClass;
96     private volatile int mScanMode;
97     private volatile int mDiscoverableTimeout;
98     private volatile ParcelUuid[] mUuids;
99 
100     private CopyOnWriteArrayList<BluetoothDevice> mBondedDevices =
101             new CopyOnWriteArrayList<BluetoothDevice>();
102 
103     private static final int SCAN_MODE_CHANGES_MAX_SIZE = 10;
104     private EvictingQueue<String> mScanModeChanges;
105 
106     private int mProfilesConnecting, mProfilesConnected, mProfilesDisconnecting;
107     private final HashMap<Integer, Pair<Integer, Integer>> mProfileConnectionState =
108             new HashMap<>();
109 
110     private final CompletableFuture<List<BufferConstraint>> mBufferConstraintList =
111             new CompletableFuture<>();
112 
113     private volatile int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
114     private volatile int mState = BluetoothAdapter.STATE_OFF;
115     private int mMaxConnectedAudioDevices = 1;
116     private boolean mA2dpOffloadEnabled = false;
117 
118     private AdapterService mService;
119     private boolean mDiscovering;
120     private long mDiscoveryEndMs; // < Time (ms since epoch) that discovery ended or will end.
121     private RemoteDevices mRemoteDevices;
122     private BluetoothAdapter mAdapter;
123     // TODO - all hw capabilities to be exposed as a class
124     private int mNumOfAdvertisementInstancesSupported;
125     private boolean mRpaOffloadSupported;
126     private int mNumOfOffloadedIrkSupported;
127     private int mNumOfOffloadedScanFilterSupported;
128     private int mOffloadedScanResultStorageBytes;
129     private int mVersSupported;
130     private int mTotNumOfTrackableAdv;
131     private boolean mIsExtendedScanSupported;
132     private boolean mIsDebugLogSupported;
133     private boolean mIsActivityAndEnergyReporting;
134     private boolean mIsLe2MPhySupported;
135     private boolean mIsLeCodedPhySupported;
136     private boolean mIsLeExtendedAdvertisingSupported;
137     private boolean mIsLePeriodicAdvertisingSupported;
138     private int mLeMaximumAdvertisingDataLength;
139     private boolean mIsOffloadedTransportDiscoveryDataScanSupported;
140 
141     private int mIsDynamicAudioBufferSizeSupported;
142     private int mDynamicAudioBufferSizeSupportedCodecsGroup1;
143     private int mDynamicAudioBufferSizeSupportedCodecsGroup2;
144 
145     private boolean mIsLePeriodicAdvertisingSyncTransferSenderSupported;
146     private boolean mIsLePeriodicAdvertisingSyncTransferRecipientSupported;
147     private boolean mIsLeConnectedIsochronousStreamCentralSupported;
148     private boolean mIsLeIsochronousBroadcasterSupported;
149     private boolean mIsLeChannelSoundingSupported;
150 
151     private boolean mReceiverRegistered;
152 
153     private final BroadcastReceiver mReceiver =
154             new BroadcastReceiver() {
155                 @Override
156                 public void onReceive(Context context, Intent intent) {
157                     String action = intent.getAction();
158                     if (action == null) {
159                         Log.w(TAG, "Received intent with null action");
160                         return;
161                     }
162                     switch (action) {
163                         case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
164                             logConnectionStateChanges(BluetoothProfile.HEADSET, intent);
165                             break;
166                         case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
167                             logConnectionStateChanges(BluetoothProfile.A2DP, intent);
168                             break;
169                         case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED:
170                             logConnectionStateChanges(BluetoothProfile.HEADSET_CLIENT, intent);
171                             break;
172                         case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
173                             logConnectionStateChanges(BluetoothProfile.HEARING_AID, intent);
174                             break;
175                         case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED:
176                             logConnectionStateChanges(BluetoothProfile.A2DP_SINK, intent);
177                             break;
178                         case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED:
179                             logConnectionStateChanges(BluetoothProfile.HID_DEVICE, intent);
180                             break;
181                         case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED:
182                             logConnectionStateChanges(BluetoothProfile.HID_HOST, intent);
183                             break;
184                         case BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED:
185                             logConnectionStateChanges(BluetoothProfile.AVRCP_CONTROLLER, intent);
186                             break;
187                         case BluetoothPan.ACTION_CONNECTION_STATE_CHANGED:
188                             logConnectionStateChanges(BluetoothProfile.PAN, intent);
189                             break;
190                         case BluetoothMap.ACTION_CONNECTION_STATE_CHANGED:
191                             logConnectionStateChanges(BluetoothProfile.MAP, intent);
192                             break;
193                         case BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED:
194                             logConnectionStateChanges(BluetoothProfile.MAP_CLIENT, intent);
195                             break;
196                         case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED:
197                             logConnectionStateChanges(BluetoothProfile.SAP, intent);
198                             break;
199                         case BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED:
200                             logConnectionStateChanges(BluetoothProfile.PBAP_CLIENT, intent);
201                             break;
202                         case BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED:
203                             logConnectionStateChanges(BluetoothProfile.PBAP, intent);
204                             break;
205                         case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
206                             logConnectionStateChanges(BluetoothProfile.LE_AUDIO, intent);
207                             break;
208                         default:
209                             Log.w(TAG, "Received unknown intent " + intent);
210                             break;
211                     }
212                 }
213             };
214 
215     // Lock for all getters and setters.
216     // If finer grained locking is needer, more locks
217     // can be added here.
218     private final Object mObject = new Object();
219 
AdapterProperties(AdapterService service)220     AdapterProperties(AdapterService service) {
221         mService = service;
222         mAdapter = BluetoothAdapter.getDefaultAdapter();
223         mScanModeChanges = EvictingQueue.create(SCAN_MODE_CHANGES_MAX_SIZE);
224         invalidateBluetoothCaches();
225     }
226 
init(RemoteDevices remoteDevices)227     public void init(RemoteDevices remoteDevices) {
228         mProfileConnectionState.clear();
229         mRemoteDevices = remoteDevices;
230 
231         // Get default max connected audio devices from config.xml
232         int configDefaultMaxConnectedAudioDevices =
233                 mService.getResources()
234                         .getInteger(
235                                 com.android.bluetooth.R.integer
236                                         .config_bluetooth_max_connected_audio_devices);
237         // Override max connected audio devices if MAX_CONNECTED_AUDIO_DEVICES_PROPERTY is set
238         int propertyOverlayedMaxConnectedAudioDevices =
239                 SystemProperties.getInt(
240                         MAX_CONNECTED_AUDIO_DEVICES_PROPERTY,
241                         configDefaultMaxConnectedAudioDevices);
242         // Make sure the final value of max connected audio devices is within allowed range
243         mMaxConnectedAudioDevices =
244                 Math.min(
245                         Math.max(
246                                 propertyOverlayedMaxConnectedAudioDevices,
247                                 MAX_CONNECTED_AUDIO_DEVICES_LOWER_BOUND),
248                         MAX_CONNECTED_AUDIO_DEVICES_UPPER_BOUND);
249         Log.i(
250                 TAG,
251                 "init(), maxConnectedAudioDevices, default="
252                         + configDefaultMaxConnectedAudioDevices
253                         + ", propertyOverlayed="
254                         + propertyOverlayedMaxConnectedAudioDevices
255                         + ", finalValue="
256                         + mMaxConnectedAudioDevices);
257 
258         mA2dpOffloadEnabled =
259                 SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false)
260                         && !SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
261 
262         IntentFilter filter = new IntentFilter();
263         filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
264         filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
265         filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
266         filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
267         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
268         filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
269         filter.addAction(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
270         filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
271         filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
272         filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
273         filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
274         filter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
275         filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
276         filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
277         filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
278         mService.registerReceiver(mReceiver, filter);
279         mReceiverRegistered = true;
280         invalidateBluetoothCaches();
281     }
282 
cleanup()283     public void cleanup() {
284         mRemoteDevices = null;
285         mProfileConnectionState.clear();
286 
287         if (mReceiverRegistered) {
288             mService.unregisterReceiver(mReceiver);
289             mReceiverRegistered = false;
290         }
291         mService = null;
292         mBondedDevices.clear();
293         mScanModeChanges.clear();
294         invalidateBluetoothCaches();
295     }
296 
invalidateGetProfileConnectionStateCache()297     private static void invalidateGetProfileConnectionStateCache() {
298         BluetoothAdapter.invalidateGetProfileConnectionStateCache();
299     }
300 
invalidateIsOffloadedFilteringSupportedCache()301     private static void invalidateIsOffloadedFilteringSupportedCache() {
302         BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache();
303     }
304 
invalidateBluetoothGetConnectionStateCache()305     private static void invalidateBluetoothGetConnectionStateCache() {
306         BluetoothMap.invalidateBluetoothGetConnectionStateCache();
307         BluetoothSap.invalidateBluetoothGetConnectionStateCache();
308     }
309 
invalidateGetConnectionStateCache()310     private static void invalidateGetConnectionStateCache() {
311         BluetoothAdapter.invalidateGetAdapterConnectionStateCache();
312     }
313 
invalidateGetBondStateCache()314     private static void invalidateGetBondStateCache() {
315         BluetoothDevice.invalidateBluetoothGetBondStateCache();
316     }
317 
invalidateBluetoothCaches()318     private static void invalidateBluetoothCaches() {
319         invalidateGetProfileConnectionStateCache();
320         invalidateIsOffloadedFilteringSupportedCache();
321         invalidateGetConnectionStateCache();
322         invalidateGetBondStateCache();
323         invalidateBluetoothGetConnectionStateCache();
324     }
325 
326     @Override
clone()327     public Object clone() throws CloneNotSupportedException {
328         throw new CloneNotSupportedException();
329     }
330 
331     /**
332      * @return the mName
333      */
getName()334     String getName() {
335         return mName;
336     }
337 
338     /**
339      * Set the local adapter property - name
340      *
341      * @param name the name to set
342      */
setName(String name)343     boolean setName(String name) {
344         synchronized (mObject) {
345             return mService.getNative()
346                     .setAdapterProperty(
347                             AbstractionLayer.BT_PROPERTY_BDNAME,
348                             Utils.truncateStringForUtf8Storage(
349                                             name, BLUETOOTH_NAME_MAX_LENGTH_BYTES)
350                                     .getBytes());
351         }
352     }
353 
354     /**
355      * @return the mScanMode
356      */
getScanMode()357     int getScanMode() {
358         return mScanMode;
359     }
360 
361     /**
362      * Set the local adapter property - scanMode
363      *
364      * @param scanMode the ScanMode to set, valid values are: { BluetoothAdapter.SCAN_MODE_NONE,
365      *     BluetoothAdapter.SCAN_MODE_CONNECTABLE,
366      *     BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, }
367      */
setScanMode(int scanMode)368     boolean setScanMode(int scanMode) {
369         addScanChangeLog(scanMode);
370         synchronized (mObject) {
371             return mService.getNative()
372                     .setAdapterProperty(
373                             AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE,
374                             Utils.intToByteArray(AdapterService.convertScanModeToHal(scanMode)));
375         }
376     }
377 
addScanChangeLog(int scanMode)378     private void addScanChangeLog(int scanMode) {
379         String time = Utils.getLocalTimeString();
380         String uidPid = Utils.getUidPidString();
381         String scanModeString = dumpScanMode(scanMode);
382 
383         mScanModeChanges.add(time + " (" + uidPid + ") " + scanModeString);
384     }
385 
386     /**
387      * @return the mUuids
388      */
getUuids()389     ParcelUuid[] getUuids() {
390         return mUuids;
391     }
392 
393     /**
394      * @return the mAddress
395      */
getAddress()396     byte[] getAddress() {
397         return mAddress;
398     }
399 
400     /**
401      * @param connectionState the mConnectionState to set
402      */
setConnectionState(int connectionState)403     void setConnectionState(int connectionState) {
404         mConnectionState = connectionState;
405         invalidateGetConnectionStateCache();
406     }
407 
408     /**
409      * @return the mConnectionState
410      */
getConnectionState()411     int getConnectionState() {
412         return mConnectionState;
413     }
414 
415     /**
416      * @param state the mState to set
417      */
setState(int state)418     void setState(int state) {
419         debugLog("Setting state to " + BluetoothAdapter.nameForState(state));
420         mState = state;
421     }
422 
423     /**
424      * @return the mState
425      */
getState()426     int getState() {
427         return mState;
428     }
429 
430     /**
431      * @return the mNumOfAdvertisementInstancesSupported
432      */
getNumOfAdvertisementInstancesSupported()433     int getNumOfAdvertisementInstancesSupported() {
434         return mNumOfAdvertisementInstancesSupported;
435     }
436 
437     /**
438      * @return the mRpaOffloadSupported
439      */
isRpaOffloadSupported()440     boolean isRpaOffloadSupported() {
441         return mRpaOffloadSupported;
442     }
443 
444     /**
445      * @return the mNumOfOffloadedIrkSupported
446      */
getNumOfOffloadedIrkSupported()447     int getNumOfOffloadedIrkSupported() {
448         return mNumOfOffloadedIrkSupported;
449     }
450 
451     /**
452      * @return the mNumOfOffloadedScanFilterSupported
453      */
getNumOfOffloadedScanFilterSupported()454     int getNumOfOffloadedScanFilterSupported() {
455         return mNumOfOffloadedScanFilterSupported;
456     }
457 
458     /**
459      * @return the mOffloadedScanResultStorageBytes
460      */
getOffloadedScanResultStorage()461     int getOffloadedScanResultStorage() {
462         return mOffloadedScanResultStorageBytes;
463     }
464 
465     /**
466      * @return tx/rx/idle activity and energy info
467      */
isActivityAndEnergyReportingSupported()468     boolean isActivityAndEnergyReportingSupported() {
469         return mIsActivityAndEnergyReporting;
470     }
471 
472     /**
473      * @return the mIsLe2MPhySupported
474      */
isLe2MPhySupported()475     boolean isLe2MPhySupported() {
476         return mIsLe2MPhySupported;
477     }
478 
479     /**
480      * @return the mIsLeCodedPhySupported
481      */
isLeCodedPhySupported()482     boolean isLeCodedPhySupported() {
483         return mIsLeCodedPhySupported;
484     }
485 
486     /**
487      * @return the mIsLeExtendedAdvertisingSupported
488      */
isLeExtendedAdvertisingSupported()489     boolean isLeExtendedAdvertisingSupported() {
490         return mIsLeExtendedAdvertisingSupported;
491     }
492 
493     /**
494      * @return the mIsLePeriodicAdvertisingSupported
495      */
isLePeriodicAdvertisingSupported()496     boolean isLePeriodicAdvertisingSupported() {
497         return mIsLePeriodicAdvertisingSupported;
498     }
499 
500     /**
501      * @return the mIsLePeriodicAdvertisingSyncTransferSenderSupported
502      */
isLePeriodicAdvertisingSyncTransferSenderSupported()503     boolean isLePeriodicAdvertisingSyncTransferSenderSupported() {
504         return mIsLePeriodicAdvertisingSyncTransferSenderSupported;
505     }
506 
507     /**
508      * @return the mIsLePeriodicAdvertisingSyncTransferRecipientSupported
509      */
isLePeriodicAdvertisingSyncTransferRecipientSupported()510     boolean isLePeriodicAdvertisingSyncTransferRecipientSupported() {
511         return mIsLePeriodicAdvertisingSyncTransferRecipientSupported;
512     }
513 
514     /**
515      * @return the mIsLeConnectedIsochronousStreamCentralSupported
516      */
isLeConnectedIsochronousStreamCentralSupported()517     boolean isLeConnectedIsochronousStreamCentralSupported() {
518         return mIsLeConnectedIsochronousStreamCentralSupported;
519     }
520 
521     /**
522      * @return the mIsLeIsochronousBroadcasterSupported
523      */
isLeIsochronousBroadcasterSupported()524     boolean isLeIsochronousBroadcasterSupported() {
525         return mIsLeIsochronousBroadcasterSupported;
526     }
527 
528     /**
529      * @return the mIsLeChannelSoundingSupported
530      */
isLeChannelSoundingSupported()531     boolean isLeChannelSoundingSupported() {
532         return mIsLeChannelSoundingSupported;
533     }
534 
535     /**
536      * @return the getLeMaximumAdvertisingDataLength
537      */
getLeMaximumAdvertisingDataLength()538     int getLeMaximumAdvertisingDataLength() {
539         return mLeMaximumAdvertisingDataLength;
540     }
541 
542     /**
543      * @return total number of trackable advertisements
544      */
getTotalNumOfTrackableAdvertisements()545     int getTotalNumOfTrackableAdvertisements() {
546         return mTotNumOfTrackableAdv;
547     }
548 
549     /**
550      * @return the isOffloadedTransportDiscoveryDataScanSupported
551      */
isOffloadedTransportDiscoveryDataScanSupported()552     public boolean isOffloadedTransportDiscoveryDataScanSupported() {
553         return mIsOffloadedTransportDiscoveryDataScanSupported;
554     }
555 
556     /**
557      * @return the maximum number of connected audio devices
558      */
getMaxConnectedAudioDevices()559     int getMaxConnectedAudioDevices() {
560         return mMaxConnectedAudioDevices;
561     }
562 
563     /**
564      * @return A2DP offload support
565      */
isA2dpOffloadEnabled()566     boolean isA2dpOffloadEnabled() {
567         return mA2dpOffloadEnabled;
568     }
569 
570     /**
571      * @return Dynamic Audio Buffer support
572      */
getDynamicBufferSupport()573     int getDynamicBufferSupport() {
574         if (!mA2dpOffloadEnabled) {
575             // TODO: Enable Dynamic Audio Buffer for A2DP software encoding when ready.
576             mIsDynamicAudioBufferSizeSupported = BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_NONE;
577         } else {
578             if ((mDynamicAudioBufferSizeSupportedCodecsGroup1 != 0)
579                     || (mDynamicAudioBufferSizeSupportedCodecsGroup2 != 0)) {
580                 mIsDynamicAudioBufferSizeSupported =
581                         BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD;
582             } else {
583                 mIsDynamicAudioBufferSizeSupported = BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_NONE;
584             }
585         }
586         return mIsDynamicAudioBufferSizeSupported;
587     }
588 
589     /**
590      * @return Dynamic Audio Buffer Capability
591      */
getBufferConstraints()592     BufferConstraints getBufferConstraints() {
593         return new BufferConstraints(mBufferConstraintList.join());
594     }
595 
596     /**
597      * Set the dynamic audio buffer size
598      *
599      * @param codec the codecs to set
600      * @param size the size to set
601      */
setBufferLengthMillis(int codec, int size)602     boolean setBufferLengthMillis(int codec, int size) {
603         return mService.getNative().setBufferLengthMillis(codec, size);
604     }
605 
606     /**
607      * @return the mBondedDevices
608      */
getBondedDevices()609     BluetoothDevice[] getBondedDevices() {
610         BluetoothDevice[] bondedDeviceList = new BluetoothDevice[0];
611         try {
612             bondedDeviceList = mBondedDevices.toArray(bondedDeviceList);
613         } catch (ArrayStoreException ee) {
614             Log.e(TAG, "Error retrieving bonded device array");
615         }
616         infoLog("getBondedDevices: length=" + bondedDeviceList.length);
617         return bondedDeviceList;
618     }
619 
620     // This function shall be invoked from BondStateMachine whenever the bond
621     // state changes.
622     @VisibleForTesting
onBondStateChanged(BluetoothDevice device, int state)623     void onBondStateChanged(BluetoothDevice device, int state) {
624         if (device == null) {
625             Log.w(TAG, "onBondStateChanged, device is null");
626             return;
627         }
628         try {
629             byte[] addrByte = Utils.getByteAddress(device);
630             DeviceProperties prop = mRemoteDevices.getDeviceProperties(device);
631             if (prop == null) {
632                 prop = mRemoteDevices.addDeviceProperties(addrByte);
633             }
634             device = prop.getDevice();
635             prop.setBondState(state);
636 
637             if (state == BluetoothDevice.BOND_BONDED) {
638                 // add if not already in list
639                 if (!mBondedDevices.contains(device)) {
640                     debugLog("Adding bonded device:" + device);
641                     mBondedDevices.add(device);
642                     cleanupPrevBondRecordsFor(device);
643                 }
644             } else if (state == BluetoothDevice.BOND_NONE) {
645                 // remove device from list
646                 if (mBondedDevices.remove(device)) {
647                     debugLog("Removing bonded device:" + device);
648                 } else {
649                     debugLog("Failed to remove device: " + device);
650                 }
651             }
652             invalidateGetBondStateCache();
653         } catch (Exception ee) {
654             Log.w(TAG, "onBondStateChanged: Exception ", ee);
655         }
656     }
657 
cleanupPrevBondRecordsFor(BluetoothDevice device)658     void cleanupPrevBondRecordsFor(BluetoothDevice device) {
659         String address = device.getAddress();
660         String identityAddress =
661                 Flags.identityAddressNullIfUnknown()
662                         ? Utils.getBrEdrAddress(device, mService)
663                         : mService.getIdentityAddress(address);
664         int deviceType = mRemoteDevices.getDeviceProperties(device).getDeviceType();
665         debugLog("cleanupPrevBondRecordsFor: " + device + ", device type: " + deviceType);
666         if (identityAddress == null) {
667             return;
668         }
669 
670         if (Flags.cleanupLeOnlyDeviceType() && deviceType != BluetoothDevice.DEVICE_TYPE_LE) {
671             return;
672         }
673 
674         for (BluetoothDevice existingDevice : mBondedDevices) {
675             String existingAddress = existingDevice.getAddress();
676             String existingIdentityAddress =
677                     Flags.identityAddressNullIfUnknown()
678                             ? Utils.getBrEdrAddress(existingDevice, mService)
679                             : mService.getIdentityAddress(existingAddress);
680             int existingDeviceType =
681                     mRemoteDevices.getDeviceProperties(existingDevice).getDeviceType();
682 
683             boolean removeExisting = false;
684             if (identityAddress.equals(existingIdentityAddress)
685                     && !address.equals(existingAddress)) {
686                 if (Flags.cleanupLeOnlyDeviceType()) {
687                     // Existing device record should be removed only if the device type is LE-only
688                     removeExisting = (existingDeviceType == BluetoothDevice.DEVICE_TYPE_LE);
689                 } else {
690                     removeExisting = true;
691                 }
692             }
693 
694             if (removeExisting) {
695                 // Found an existing LE-only device with the same identity address but different
696                 // pseudo address
697                 if (mService.getNative().removeBond(Utils.getBytesFromAddress(existingAddress))) {
698                     mBondedDevices.remove(existingDevice);
699                     infoLog(
700                             "Removing old bond record: "
701                                     + existingDevice
702                                     + " for the device: "
703                                     + device);
704                 } else {
705                     Log.e(
706                             TAG,
707                             "Unexpected error while removing old bond record:"
708                                     + existingDevice
709                                     + " for the device: "
710                                     + device);
711                 }
712                 break;
713             }
714         }
715     }
716 
getDiscoverableTimeout()717     int getDiscoverableTimeout() {
718         return mDiscoverableTimeout;
719     }
720 
setDiscoverableTimeout(int timeout)721     boolean setDiscoverableTimeout(int timeout) {
722         synchronized (mObject) {
723             return mService.getNative()
724                     .setAdapterProperty(
725                             AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT,
726                             Utils.intToByteArray(timeout));
727         }
728     }
729 
getProfileConnectionState(int profile)730     int getProfileConnectionState(int profile) {
731         synchronized (mObject) {
732             Pair<Integer, Integer> p = mProfileConnectionState.get(profile);
733             if (p != null) {
734                 return p.first;
735             }
736             return BluetoothProfile.STATE_DISCONNECTED;
737         }
738     }
739 
discoveryEndMillis()740     long discoveryEndMillis() {
741         return mDiscoveryEndMs;
742     }
743 
isDiscovering()744     boolean isDiscovering() {
745         return mDiscovering;
746     }
747 
748     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
logConnectionStateChanges(int profile, Intent connIntent)749     private void logConnectionStateChanges(int profile, Intent connIntent) {
750         BluetoothDevice device = connIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
751         int state = connIntent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
752         int metricId = mService.getMetricId(device);
753         byte[] remoteDeviceInfoBytes = MetricsLogger.getInstance().getRemoteDeviceInfoProto(device);
754         if (state == BluetoothProfile.STATE_CONNECTING) {
755             BluetoothStatsLog.write(
756                     BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED, metricId, device.getName());
757             BluetoothStatsLog.write(
758                     BluetoothStatsLog.REMOTE_DEVICE_INFORMATION_WITH_METRIC_ID,
759                     metricId,
760                     remoteDeviceInfoBytes);
761             MetricsLogger.getInstance()
762                     .logAllowlistedDeviceNameHash(metricId, device.getName(), true);
763         }
764         BluetoothStatsLog.write(
765                 BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED,
766                 state,
767                 0 /* deprecated */,
768                 profile,
769                 mService.obfuscateAddress(device),
770                 metricId,
771                 0,
772                 -1);
773     }
774 
775     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
updateOnProfileConnectionChanged( BluetoothDevice device, int profile, int newState, int prevState)776     void updateOnProfileConnectionChanged(
777             BluetoothDevice device, int profile, int newState, int prevState) {
778         String logInfo =
779                 ("profile=" + BluetoothProfile.getProfileName(profile))
780                         + (" device=" + device)
781                         + (" state [" + prevState + " -> " + newState + "]");
782         Log.d(TAG, "updateOnProfileConnectionChanged: " + logInfo);
783         if (!isNormalStateTransition(prevState, newState)) {
784             Log.w(TAG, "updateOnProfileConnectionChanged: Unexpected transition. " + logInfo);
785         }
786         BluetoothStatsLog.write(
787                 BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED,
788                 newState,
789                 0 /* deprecated */,
790                 profile,
791                 mService.obfuscateAddress(device),
792                 mService.getMetricId(device),
793                 0,
794                 SYSTEM_CONNECTION_LATENCY_METRIC);
795         if (!validateProfileConnectionState(newState)
796                 || !validateProfileConnectionState(prevState)) {
797             // Previously, an invalid state was broadcast anyway,
798             // with the invalid state converted to -1 in the intent.
799             // Better to log an error and not send an intent with
800             // invalid contents or set mAdapterConnectionState to -1.
801             Log.e(TAG, "updateOnProfileConnectionChanged: Invalid transition. " + logInfo);
802             return;
803         }
804 
805         synchronized (mObject) {
806             updateProfileConnectionState(profile, newState, prevState);
807 
808             if (updateCountersAndCheckForConnectionStateChange(newState, prevState)) {
809                 int newAdapterState = convertToAdapterState(newState);
810                 int prevAdapterState = convertToAdapterState(prevState);
811                 setConnectionState(newAdapterState);
812 
813                 Intent intent =
814                         new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)
815                                 .putExtra(BluetoothDevice.EXTRA_DEVICE, device)
816                                 .putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, newAdapterState)
817                                 .putExtra(
818                                         BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
819                                         prevAdapterState)
820                                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
821                 Log.d(TAG, "updateOnProfileConnectionChanged: " + logInfo);
822                 mService.sendBroadcastAsUser(
823                         intent,
824                         UserHandle.ALL,
825                         BLUETOOTH_CONNECT,
826                         Utils.getTempBroadcastOptions().toBundle());
827             }
828         }
829     }
830 
validateProfileConnectionState(int state)831     private boolean validateProfileConnectionState(int state) {
832         return (state == BluetoothProfile.STATE_DISCONNECTED
833                 || state == BluetoothProfile.STATE_CONNECTING
834                 || state == BluetoothProfile.STATE_CONNECTED
835                 || state == BluetoothProfile.STATE_DISCONNECTING);
836     }
837 
convertToAdapterState(int state)838     private static int convertToAdapterState(int state) {
839         switch (state) {
840             case BluetoothProfile.STATE_DISCONNECTED:
841                 return BluetoothAdapter.STATE_DISCONNECTED;
842             case BluetoothProfile.STATE_DISCONNECTING:
843                 return BluetoothAdapter.STATE_DISCONNECTING;
844             case BluetoothProfile.STATE_CONNECTED:
845                 return BluetoothAdapter.STATE_CONNECTED;
846             case BluetoothProfile.STATE_CONNECTING:
847                 return BluetoothAdapter.STATE_CONNECTING;
848         }
849         Log.e(TAG, "convertToAdapterState, unknow state " + state);
850         return -1;
851     }
852 
isNormalStateTransition(int prevState, int nextState)853     private static boolean isNormalStateTransition(int prevState, int nextState) {
854         switch (prevState) {
855             case BluetoothProfile.STATE_DISCONNECTED:
856                 return nextState == BluetoothProfile.STATE_CONNECTING;
857             case BluetoothProfile.STATE_CONNECTED:
858                 return nextState == BluetoothProfile.STATE_DISCONNECTING;
859             case BluetoothProfile.STATE_DISCONNECTING:
860             case BluetoothProfile.STATE_CONNECTING:
861                 return (nextState == BluetoothProfile.STATE_DISCONNECTED)
862                         || (nextState == BluetoothProfile.STATE_CONNECTED);
863             default:
864                 return false;
865         }
866     }
867 
updateCountersAndCheckForConnectionStateChange(int state, int prevState)868     private boolean updateCountersAndCheckForConnectionStateChange(int state, int prevState) {
869         switch (prevState) {
870             case BluetoothProfile.STATE_CONNECTING:
871                 if (mProfilesConnecting > 0) {
872                     mProfilesConnecting--;
873                 } else {
874                     Log.e(TAG, "mProfilesConnecting " + mProfilesConnecting);
875                     throw new IllegalStateException(
876                             "Invalid state transition, " + prevState + " -> " + state);
877                 }
878                 break;
879 
880             case BluetoothProfile.STATE_CONNECTED:
881                 if (mProfilesConnected > 0) {
882                     mProfilesConnected--;
883                 } else {
884                     Log.e(TAG, "mProfilesConnected " + mProfilesConnected);
885                     throw new IllegalStateException(
886                             "Invalid state transition, " + prevState + " -> " + state);
887                 }
888                 break;
889 
890             case BluetoothProfile.STATE_DISCONNECTING:
891                 if (mProfilesDisconnecting > 0) {
892                     mProfilesDisconnecting--;
893                 } else {
894                     Log.e(TAG, "mProfilesDisconnecting " + mProfilesDisconnecting);
895                     throw new IllegalStateException(
896                             "Invalid state transition, " + prevState + " -> " + state);
897                 }
898                 break;
899         }
900 
901         switch (state) {
902             case BluetoothProfile.STATE_CONNECTING:
903                 mProfilesConnecting++;
904                 return (mProfilesConnected == 0 && mProfilesConnecting == 1);
905 
906             case BluetoothProfile.STATE_CONNECTED:
907                 mProfilesConnected++;
908                 return (mProfilesConnected == 1);
909 
910             case BluetoothProfile.STATE_DISCONNECTING:
911                 mProfilesDisconnecting++;
912                 return (mProfilesConnected == 0 && mProfilesDisconnecting == 1);
913 
914             case BluetoothProfile.STATE_DISCONNECTED:
915                 return (mProfilesConnected == 0 && mProfilesConnecting == 0);
916 
917             default:
918                 return true;
919         }
920     }
921 
updateProfileConnectionState(int profile, int newState, int oldState)922     private void updateProfileConnectionState(int profile, int newState, int oldState) {
923         // mProfileConnectionState is a hashmap -
924         // <Integer, Pair<Integer, Integer>>
925         // The key is the profile, the value is a pair. first element
926         // is the state and the second element is the number of devices
927         // in that state.
928         int numDev = 1;
929         int newHashState = newState;
930         boolean update = true;
931 
932         // The following conditions are considered in this function:
933         // 1. If there is no record of profile and state - update
934         // 2. If a new device's state is current hash state - increment
935         //    number of devices in the state.
936         // 3. If a state change has happened to Connected or Connecting
937         //    (if current state is not connected), update.
938         // 4. If numDevices is 1 and that device state is being updated, update
939         // 5. If numDevices is > 1 and one of the devices is changing state,
940         //    decrement numDevices but maintain oldState if it is Connected or
941         //    Connecting
942         Pair<Integer, Integer> stateNumDev = mProfileConnectionState.get(profile);
943         if (stateNumDev != null) {
944             int currHashState = stateNumDev.first;
945             numDev = stateNumDev.second;
946 
947             if (newState == currHashState) {
948                 numDev++;
949             } else if (newState == BluetoothProfile.STATE_CONNECTED
950                     || (newState == BluetoothProfile.STATE_CONNECTING
951                             && currHashState != BluetoothProfile.STATE_CONNECTED)) {
952                 numDev = 1;
953             } else if (numDev == 1 && oldState == currHashState) {
954                 update = true;
955             } else if (numDev > 1 && oldState == currHashState) {
956                 numDev--;
957 
958                 if (currHashState == BluetoothProfile.STATE_CONNECTED
959                         || currHashState == BluetoothProfile.STATE_CONNECTING) {
960                     newHashState = currHashState;
961                 }
962             } else {
963                 update = false;
964             }
965         }
966 
967         if (update) {
968             mProfileConnectionState.put(profile, new Pair<Integer, Integer>(newHashState, numDev));
969             invalidateGetProfileConnectionStateCache();
970         }
971     }
972 
973     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
adapterPropertyChangedCallback(int[] types, byte[][] values)974     void adapterPropertyChangedCallback(int[] types, byte[][] values) {
975         Intent intent;
976         int type;
977         byte[] val;
978         for (int i = 0; i < types.length; i++) {
979             val = values[i];
980             type = types[i];
981             infoLog("adapterPropertyChangedCallback with type:" + type + " len:" + val.length);
982             synchronized (mObject) {
983                 switch (type) {
984                     case AbstractionLayer.BT_PROPERTY_BDNAME:
985                         mName = new String(val);
986                         intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
987                         intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
988                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
989                         mService.sendBroadcastAsUser(
990                                 intent,
991                                 UserHandle.ALL,
992                                 BLUETOOTH_CONNECT,
993                                 Utils.getTempBroadcastOptions().toBundle());
994                         debugLog("Name is: " + mName);
995                         break;
996                     case AbstractionLayer.BT_PROPERTY_BDADDR:
997                         mAddress = val;
998                         String address = Utils.getAddressStringFromByte(mAddress);
999                         intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
1000                         intent.putExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS, address);
1001                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1002                         mService.sendBroadcastAsUser(
1003                                 intent,
1004                                 UserHandle.ALL,
1005                                 BLUETOOTH_CONNECT,
1006                                 Utils.getTempBroadcastOptions().toBundle());
1007                         break;
1008                     case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE:
1009                         if (val == null || val.length != 3) {
1010                             debugLog("Invalid BT CoD value from stack.");
1011                             return;
1012                         }
1013                         int bluetoothClass =
1014                                 ((int) val[0] << 16) + ((int) val[1] << 8) + (int) val[2];
1015                         if (bluetoothClass != 0) {
1016                             mBluetoothClass = new BluetoothClass(bluetoothClass);
1017                         }
1018                         debugLog("BT Class:" + mBluetoothClass);
1019                         break;
1020                     case AbstractionLayer.BT_PROPERTY_ADAPTER_SCAN_MODE:
1021                         int mode = Utils.byteArrayToInt(val, 0);
1022                         mScanMode = AdapterService.convertScanModeFromHal(mode);
1023                         intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
1024                         intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode);
1025                         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1026                         mService.sendBroadcast(
1027                                 intent, BLUETOOTH_SCAN, Utils.getTempBroadcastOptions().toBundle());
1028                         debugLog("Scan Mode:" + mScanMode);
1029                         break;
1030                     case AbstractionLayer.BT_PROPERTY_UUIDS:
1031                         mUuids = Utils.byteArrayToUuid(val);
1032                         break;
1033                     case AbstractionLayer.BT_PROPERTY_ADAPTER_BONDED_DEVICES:
1034                         int number = val.length / BD_ADDR_LEN;
1035                         byte[] addrByte = new byte[BD_ADDR_LEN];
1036                         for (int j = 0; j < number; j++) {
1037                             System.arraycopy(val, j * BD_ADDR_LEN, addrByte, 0, BD_ADDR_LEN);
1038                             onBondStateChanged(
1039                                     mAdapter.getRemoteDevice(
1040                                             Utils.getAddressStringFromByte(addrByte)),
1041                                     BluetoothDevice.BOND_BONDED);
1042                         }
1043                         break;
1044                     case AbstractionLayer.BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT:
1045                         mDiscoverableTimeout = Utils.byteArrayToInt(val, 0);
1046                         debugLog("Discoverable Timeout:" + mDiscoverableTimeout);
1047                         break;
1048 
1049                     case AbstractionLayer.BT_PROPERTY_LOCAL_LE_FEATURES:
1050                         updateFeatureSupport(val);
1051                         mService.updateLeAudioProfileServiceState();
1052                         break;
1053 
1054                     case AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER:
1055                         updateDynamicAudioBufferSupport(val);
1056                         break;
1057 
1058                     default:
1059                         Log.e(TAG, "Property change not handled in Java land:" + type);
1060                 }
1061             }
1062         }
1063     }
1064 
updateFeatureSupport(byte[] val)1065     private void updateFeatureSupport(byte[] val) {
1066         mVersSupported = ((0xFF & ((int) val[1])) << 8) + (0xFF & ((int) val[0]));
1067         mNumOfAdvertisementInstancesSupported = (0xFF & ((int) val[3]));
1068         mRpaOffloadSupported = ((0xFF & ((int) val[4])) != 0);
1069         mNumOfOffloadedIrkSupported = (0xFF & ((int) val[5]));
1070         mNumOfOffloadedScanFilterSupported = (0xFF & ((int) val[6]));
1071         mIsActivityAndEnergyReporting = ((0xFF & ((int) val[7])) != 0);
1072         mOffloadedScanResultStorageBytes = ((0xFF & ((int) val[9])) << 8) + (0xFF & ((int) val[8]));
1073         mTotNumOfTrackableAdv = ((0xFF & ((int) val[11])) << 8) + (0xFF & ((int) val[10]));
1074         mIsExtendedScanSupported = ((0xFF & ((int) val[12])) != 0);
1075         mIsDebugLogSupported = ((0xFF & ((int) val[13])) != 0);
1076         mIsLe2MPhySupported = ((0xFF & ((int) val[14])) != 0);
1077         mIsLeCodedPhySupported = ((0xFF & ((int) val[15])) != 0);
1078         mIsLeExtendedAdvertisingSupported = ((0xFF & ((int) val[16])) != 0);
1079         mIsLePeriodicAdvertisingSupported = ((0xFF & ((int) val[17])) != 0);
1080         mLeMaximumAdvertisingDataLength =
1081                 (0xFF & ((int) val[18])) + ((0xFF & ((int) val[19])) << 8);
1082         mDynamicAudioBufferSizeSupportedCodecsGroup1 =
1083                 ((0xFF & ((int) val[21])) << 8) + (0xFF & ((int) val[20]));
1084         mDynamicAudioBufferSizeSupportedCodecsGroup2 =
1085                 ((0xFF & ((int) val[23])) << 8) + (0xFF & ((int) val[22]));
1086         mIsLePeriodicAdvertisingSyncTransferSenderSupported = ((0xFF & ((int) val[24])) != 0);
1087         mIsLeConnectedIsochronousStreamCentralSupported = ((0xFF & ((int) val[25])) != 0);
1088         mIsLeIsochronousBroadcasterSupported = ((0xFF & ((int) val[26])) != 0);
1089         mIsLePeriodicAdvertisingSyncTransferRecipientSupported = ((0xFF & ((int) val[27])) != 0);
1090         mIsOffloadedTransportDiscoveryDataScanSupported = ((0x01 & ((int) val[28])) != 0);
1091         mIsLeChannelSoundingSupported = ((0xFF & ((int) val[30])) != 0);
1092 
1093         Log.d(
1094                 TAG,
1095                 "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller"
1096                         + " mNumOfAdvertisementInstancesSupported = "
1097                         + mNumOfAdvertisementInstancesSupported
1098                         + " mRpaOffloadSupported = "
1099                         + mRpaOffloadSupported
1100                         + " mNumOfOffloadedIrkSupported = "
1101                         + mNumOfOffloadedIrkSupported
1102                         + " mNumOfOffloadedScanFilterSupported = "
1103                         + mNumOfOffloadedScanFilterSupported
1104                         + " mOffloadedScanResultStorageBytes= "
1105                         + mOffloadedScanResultStorageBytes
1106                         + " mIsActivityAndEnergyReporting = "
1107                         + mIsActivityAndEnergyReporting
1108                         + " mVersSupported = "
1109                         + mVersSupported
1110                         + " mTotNumOfTrackableAdv = "
1111                         + mTotNumOfTrackableAdv
1112                         + " mIsExtendedScanSupported = "
1113                         + mIsExtendedScanSupported
1114                         + " mIsDebugLogSupported = "
1115                         + mIsDebugLogSupported
1116                         + " mIsLe2MPhySupported = "
1117                         + mIsLe2MPhySupported
1118                         + " mIsLeCodedPhySupported = "
1119                         + mIsLeCodedPhySupported
1120                         + " mIsLeExtendedAdvertisingSupported = "
1121                         + mIsLeExtendedAdvertisingSupported
1122                         + " mIsLePeriodicAdvertisingSupported = "
1123                         + mIsLePeriodicAdvertisingSupported
1124                         + " mLeMaximumAdvertisingDataLength = "
1125                         + mLeMaximumAdvertisingDataLength
1126                         + " mDynamicAudioBufferSizeSupportedCodecsGroup1 = "
1127                         + mDynamicAudioBufferSizeSupportedCodecsGroup1
1128                         + " mDynamicAudioBufferSizeSupportedCodecsGroup2 = "
1129                         + mDynamicAudioBufferSizeSupportedCodecsGroup2
1130                         + " mIsLePeriodicAdvertisingSyncTransferSenderSupported = "
1131                         + mIsLePeriodicAdvertisingSyncTransferSenderSupported
1132                         + " mIsLeConnectedIsochronousStreamCentralSupported = "
1133                         + mIsLeConnectedIsochronousStreamCentralSupported
1134                         + " mIsLeIsochronousBroadcasterSupported = "
1135                         + mIsLeIsochronousBroadcasterSupported
1136                         + " mIsLePeriodicAdvertisingSyncTransferRecipientSupported = "
1137                         + mIsLePeriodicAdvertisingSyncTransferRecipientSupported
1138                         + " mIsOffloadedTransportDiscoveryDataScanSupported = "
1139                         + mIsOffloadedTransportDiscoveryDataScanSupported
1140                         + " mIsLeChannelSoundingSupported = "
1141                         + mIsLeChannelSoundingSupported);
1142         invalidateIsOffloadedFilteringSupportedCache();
1143     }
1144 
updateDynamicAudioBufferSupport(byte[] val)1145     private void updateDynamicAudioBufferSupport(byte[] val) {
1146         if (mBufferConstraintList.isDone()) {
1147             return;
1148         }
1149 
1150         // bufferConstraints is the table indicates the capability of all the codecs
1151         // with buffer time. The raw is codec number, and the column is buffer type. There are 3
1152         // buffer types - default/maximum/minimum.
1153         // The maximum number of raw is BUFFER_CODEC_MAX_NUM(32).
1154         // The maximum number of column is BUFFER_TYPE_MAX(3).
1155         // The array element indicates the buffer time, the size is two octet.
1156         List<BufferConstraint> bufferConstraintList = new ArrayList<BufferConstraint>();
1157 
1158         for (int i = 0; i < BufferConstraints.BUFFER_CODEC_MAX_NUM; i++) {
1159             int defaultBufferTime =
1160                     ((0xFF & ((int) val[i * 6 + 1])) << 8) + (0xFF & ((int) val[i * 6]));
1161             int maximumBufferTime =
1162                     ((0xFF & ((int) val[i * 6 + 3])) << 8) + (0xFF & ((int) val[i * 6 + 2]));
1163             int minimumBufferTime =
1164                     ((0xFF & ((int) val[i * 6 + 5])) << 8) + (0xFF & ((int) val[i * 6 + 4]));
1165             bufferConstraintList.add(
1166                     new BufferConstraint(defaultBufferTime, maximumBufferTime, minimumBufferTime));
1167         }
1168 
1169         mBufferConstraintList.complete(bufferConstraintList);
1170     }
1171 
onBluetoothReady()1172     void onBluetoothReady() {
1173         debugLog(
1174                 "onBluetoothReady, state="
1175                         + BluetoothAdapter.nameForState(getState())
1176                         + ", ScanMode="
1177                         + mScanMode);
1178 
1179         synchronized (mObject) {
1180             // Reset adapter and profile connection states
1181             setConnectionState(BluetoothAdapter.STATE_DISCONNECTED);
1182             mProfileConnectionState.clear();
1183             invalidateGetProfileConnectionStateCache();
1184             mProfilesConnected = 0;
1185             mProfilesConnecting = 0;
1186             mProfilesDisconnecting = 0;
1187             // adapterPropertyChangedCallback has already been received.  Set the scan mode.
1188             setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
1189             // This keeps NV up-to date on first-boot after flash.
1190             setDiscoverableTimeout(mDiscoverableTimeout);
1191         }
1192     }
1193 
onBleDisable()1194     void onBleDisable() {
1195         // Sequence BLE_ON to STATE_OFF - that is _complete_ OFF state.
1196         debugLog("onBleDisable");
1197         // Set the scan_mode to NONE (no incoming connections).
1198         setScanMode(BluetoothAdapter.SCAN_MODE_NONE);
1199     }
1200 
discoveryStateChangeCallback(int state)1201     void discoveryStateChangeCallback(int state) {
1202         infoLog("Callback:discoveryStateChangeCallback with state:" + state);
1203         synchronized (mObject) {
1204             Intent intent;
1205             if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) {
1206                 mDiscovering = false;
1207                 mService.clearDiscoveringPackages();
1208                 mDiscoveryEndMs = System.currentTimeMillis();
1209                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
1210                 mService.sendBroadcast(
1211                         intent, BLUETOOTH_SCAN, getBroadcastOptionsForDiscoveryFinished());
1212             } else if (state == AbstractionLayer.BT_DISCOVERY_STARTED) {
1213                 mDiscovering = true;
1214                 mDiscoveryEndMs = System.currentTimeMillis() + DEFAULT_DISCOVERY_TIMEOUT_MS;
1215                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
1216                 mService.sendBroadcast(
1217                         intent, BLUETOOTH_SCAN, Utils.getTempBroadcastOptions().toBundle());
1218             }
1219         }
1220     }
1221 
1222     /**
1223      * @return broadcast options for ACTION_DISCOVERY_FINISHED broadcast
1224      */
getBroadcastOptionsForDiscoveryFinished()1225     private static @NonNull Bundle getBroadcastOptionsForDiscoveryFinished() {
1226         final BroadcastOptions options = Utils.getTempBroadcastOptions();
1227         if (SdkLevel.isAtLeastU()) {
1228             options.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
1229             options.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
1230         }
1231         return options.toBundle();
1232     }
1233 
1234     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
dump(FileDescriptor fd, PrintWriter writer, String[] args)1235     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1236         writer.println(TAG);
1237         writer.println("  " + "Name: " + getName());
1238         writer.println("  " + "Address: " + Utils.getAddressStringFromByte(mAddress));
1239         writer.println("  " + "ScanMode: " + dumpScanMode(getScanMode()));
1240         writer.println("  " + "ConnectionState: " + dumpConnectionState(getConnectionState()));
1241         writer.println("  " + "State: " + BluetoothAdapter.nameForState(getState()));
1242         writer.println("  " + "MaxConnectedAudioDevices: " + getMaxConnectedAudioDevices());
1243         writer.println("  " + "A2dpOffloadEnabled: " + mA2dpOffloadEnabled);
1244         writer.println("  " + "Discovering: " + mDiscovering);
1245         writer.println("  " + "DiscoveryEndMs: " + mDiscoveryEndMs);
1246 
1247         writer.println("  " + "Bonded devices:");
1248         StringBuilder sb = new StringBuilder();
1249         for (BluetoothDevice device : mBondedDevices) {
1250             String address = device.getAddress();
1251             BluetoothClass cod = device.getBluetoothClass();
1252             int codInt = cod != null ? cod.getClassOfDevice() : 0;
1253             String brEdrAddress =
1254                     Flags.identityAddressNullIfUnknown()
1255                             ? Utils.getBrEdrAddress(device)
1256                             : mService.getIdentityAddress(address);
1257             if (brEdrAddress.equals(address)) {
1258                 writer.println(
1259                         "    "
1260                                 + address
1261                                 + " ["
1262                                 + dumpDeviceType(device.getType())
1263                                 + "][ 0x"
1264                                 + String.format("%06X", codInt)
1265                                 + " ] "
1266                                 + Utils.getName(device));
1267             } else {
1268                 sb.append(
1269                         "    "
1270                                 + address
1271                                 + " => "
1272                                 + brEdrAddress
1273                                 + " ["
1274                                 + dumpDeviceType(device.getType())
1275                                 + "][ 0x"
1276                                 + String.format("%06X", codInt)
1277                                 + " ] "
1278                                 + Utils.getName(device)
1279                                 + "\n");
1280             }
1281         }
1282         writer.println(sb.toString());
1283 
1284         writer.println("  " + "Scan Mode Changes:");
1285         for (String log : mScanModeChanges) {
1286             writer.println("    " + log);
1287         }
1288     }
1289 
dumpDeviceType(int deviceType)1290     private String dumpDeviceType(int deviceType) {
1291         switch (deviceType) {
1292             case BluetoothDevice.DEVICE_TYPE_UNKNOWN:
1293                 return " ???? ";
1294             case BluetoothDevice.DEVICE_TYPE_CLASSIC:
1295                 return "BR/EDR";
1296             case BluetoothDevice.DEVICE_TYPE_LE:
1297                 return "  LE  ";
1298             case BluetoothDevice.DEVICE_TYPE_DUAL:
1299                 return " DUAL ";
1300             default:
1301                 return "Invalid device type: " + deviceType;
1302         }
1303     }
1304 
dumpConnectionState(int state)1305     private String dumpConnectionState(int state) {
1306         switch (state) {
1307             case BluetoothAdapter.STATE_DISCONNECTED:
1308                 return "STATE_DISCONNECTED";
1309             case BluetoothAdapter.STATE_DISCONNECTING:
1310                 return "STATE_DISCONNECTING";
1311             case BluetoothAdapter.STATE_CONNECTING:
1312                 return "STATE_CONNECTING";
1313             case BluetoothAdapter.STATE_CONNECTED:
1314                 return "STATE_CONNECTED";
1315             default:
1316                 return "Unknown Connection State " + state;
1317         }
1318     }
1319 
dumpScanMode(int scanMode)1320     private String dumpScanMode(int scanMode) {
1321         switch (scanMode) {
1322             case BluetoothAdapter.SCAN_MODE_NONE:
1323                 return "SCAN_MODE_NONE";
1324             case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
1325                 return "SCAN_MODE_CONNECTABLE";
1326             case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
1327                 return "SCAN_MODE_CONNECTABLE_DISCOVERABLE";
1328             default:
1329                 return "Unknown Scan Mode " + scanMode;
1330         }
1331     }
1332 
infoLog(String msg)1333     private static void infoLog(String msg) {
1334         Log.i(TAG, msg);
1335     }
1336 
debugLog(String msg)1337     private static void debugLog(String msg) {
1338         Log.d(TAG, msg);
1339     }
1340 }
1341