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