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