• 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_PRIVILEGED;
22 import static android.Manifest.permission.BLUETOOTH_SCAN;
23 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
24 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
25 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
26 import static android.bluetooth.BluetoothAdapter.nameForState;
27 import static android.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
28 import static android.bluetooth.BluetoothDevice.BOND_NONE;
29 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
30 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
31 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
32 import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
33 import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
34 import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
35 import static android.bluetooth.BluetoothProfile.getProfileName;
36 import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer;
37 import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
38 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
39 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
40 
41 import static com.android.bluetooth.Utils.getBytesFromAddress;
42 import static com.android.bluetooth.Utils.isDualModeAudioEnabled;
43 import static com.android.bluetooth.Utils.isPackageNameAccurate;
44 import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
45 
46 import static java.util.Objects.requireNonNull;
47 
48 import android.annotation.NonNull;
49 import android.annotation.Nullable;
50 import android.annotation.RequiresPermission;
51 import android.annotation.SuppressLint;
52 import android.app.AppOpsManager;
53 import android.app.PendingIntent;
54 import android.app.Service;
55 import android.app.admin.DevicePolicyManager;
56 import android.bluetooth.BluetoothA2dp;
57 import android.bluetooth.BluetoothActivityEnergyInfo;
58 import android.bluetooth.BluetoothAdapter;
59 import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile;
60 import android.bluetooth.BluetoothAdapter.ActiveDeviceUse;
61 import android.bluetooth.BluetoothDevice;
62 import android.bluetooth.BluetoothDevice.BluetoothAddress;
63 import android.bluetooth.BluetoothFrameworkInitializer;
64 import android.bluetooth.BluetoothLeAudio;
65 import android.bluetooth.BluetoothMap;
66 import android.bluetooth.BluetoothProfile;
67 import android.bluetooth.BluetoothQualityReport;
68 import android.bluetooth.BluetoothSap;
69 import android.bluetooth.BluetoothServerSocket;
70 import android.bluetooth.BluetoothSinkAudioPolicy;
71 import android.bluetooth.BluetoothSocket;
72 import android.bluetooth.BluetoothStatusCodes;
73 import android.bluetooth.BluetoothUtils;
74 import android.bluetooth.BluetoothUuid;
75 import android.bluetooth.BufferConstraints;
76 import android.bluetooth.IBluetoothCallback;
77 import android.bluetooth.IBluetoothConnectionCallback;
78 import android.bluetooth.IBluetoothMetadataListener;
79 import android.bluetooth.IBluetoothOobDataCallback;
80 import android.bluetooth.IBluetoothPreferredAudioProfilesCallback;
81 import android.bluetooth.IBluetoothQualityReportReadyCallback;
82 import android.bluetooth.IncomingRfcommSocketInfo;
83 import android.bluetooth.OobData;
84 import android.bluetooth.UidTraffic;
85 import android.bluetooth.rfcomm.BluetoothRfcommProtoEnums;
86 import android.companion.CompanionDeviceManager;
87 import android.content.AttributionSource;
88 import android.content.Context;
89 import android.content.Intent;
90 import android.content.SharedPreferences;
91 import android.content.pm.PackageManager;
92 import android.hardware.devicestate.DeviceStateManager;
93 import android.os.AsyncTask;
94 import android.os.BatteryStatsManager;
95 import android.os.Binder;
96 import android.os.Build;
97 import android.os.Bundle;
98 import android.os.Handler;
99 import android.os.IBinder;
100 import android.os.Looper;
101 import android.os.Message;
102 import android.os.ParcelUuid;
103 import android.os.Parcelable;
104 import android.os.PowerManager;
105 import android.os.RemoteCallbackList;
106 import android.os.RemoteException;
107 import android.os.SystemClock;
108 import android.os.UserHandle;
109 import android.os.UserManager;
110 import android.provider.DeviceConfig;
111 import android.provider.Settings;
112 import android.sysprop.BluetoothProperties;
113 import android.text.TextUtils;
114 import android.util.Log;
115 import android.util.Pair;
116 import android.util.SparseArray;
117 
118 import com.android.bluetooth.BluetoothEventLogger;
119 import com.android.bluetooth.BluetoothStatsLog;
120 import com.android.bluetooth.R;
121 import com.android.bluetooth.Utils;
122 import com.android.bluetooth.a2dp.A2dpService;
123 import com.android.bluetooth.a2dpsink.A2dpSinkService;
124 import com.android.bluetooth.avrcp.AvrcpTargetService;
125 import com.android.bluetooth.avrcpcontroller.AvrcpControllerService;
126 import com.android.bluetooth.bas.BatteryService;
127 import com.android.bluetooth.bass_client.BassClientService;
128 import com.android.bluetooth.btservice.InteropUtil.InteropFeature;
129 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
130 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreNativeInterface;
131 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService;
132 import com.android.bluetooth.btservice.storage.DatabaseManager;
133 import com.android.bluetooth.btservice.storage.MetadataDatabase;
134 import com.android.bluetooth.csip.CsipSetCoordinatorService;
135 import com.android.bluetooth.flags.Flags;
136 import com.android.bluetooth.gatt.GattService;
137 import com.android.bluetooth.hap.HapClientService;
138 import com.android.bluetooth.hearingaid.HearingAidService;
139 import com.android.bluetooth.hfp.HeadsetService;
140 import com.android.bluetooth.hfpclient.HeadsetClientService;
141 import com.android.bluetooth.hid.HidDeviceService;
142 import com.android.bluetooth.hid.HidHostService;
143 import com.android.bluetooth.le_audio.LeAudioService;
144 import com.android.bluetooth.le_scan.ScanController;
145 import com.android.bluetooth.le_scan.ScanManager;
146 import com.android.bluetooth.map.BluetoothMapService;
147 import com.android.bluetooth.mapclient.MapClientService;
148 import com.android.bluetooth.mcp.McpService;
149 import com.android.bluetooth.opp.BluetoothOppService;
150 import com.android.bluetooth.pan.PanService;
151 import com.android.bluetooth.pbap.BluetoothPbapService;
152 import com.android.bluetooth.pbapclient.PbapClientService;
153 import com.android.bluetooth.sap.SapService;
154 import com.android.bluetooth.sdp.SdpManager;
155 import com.android.bluetooth.tbs.TbsService;
156 import com.android.bluetooth.telephony.BluetoothInCallService;
157 import com.android.bluetooth.vc.VolumeControlService;
158 import com.android.internal.annotations.GuardedBy;
159 import com.android.internal.annotations.VisibleForTesting;
160 import com.android.modules.utils.BackgroundThread;
161 import com.android.modules.utils.BytesMatcher;
162 
163 import java.io.FileDescriptor;
164 import java.io.IOException;
165 import java.io.PrintWriter;
166 import java.nio.file.FileVisitResult;
167 import java.nio.file.Files;
168 import java.nio.file.Path;
169 import java.nio.file.Paths;
170 import java.nio.file.SimpleFileVisitor;
171 import java.nio.file.attribute.BasicFileAttributes;
172 import java.time.Duration;
173 import java.time.Instant;
174 import java.util.ArrayDeque;
175 import java.util.ArrayList;
176 import java.util.Arrays;
177 import java.util.HashMap;
178 import java.util.HashSet;
179 import java.util.Iterator;
180 import java.util.List;
181 import java.util.Locale;
182 import java.util.Map;
183 import java.util.Objects;
184 import java.util.Optional;
185 import java.util.Set;
186 import java.util.UUID;
187 import java.util.concurrent.ConcurrentHashMap;
188 import java.util.concurrent.ConcurrentLinkedQueue;
189 import java.util.concurrent.Executor;
190 import java.util.function.Function;
191 import java.util.function.Predicate;
192 import java.util.regex.Pattern;
193 
194 public class AdapterService extends Service {
195     private static final String TAG =
196             Utils.TAG_PREFIX_BLUETOOTH + AdapterService.class.getSimpleName();
197 
198     private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1;
199     private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
200     private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;
201     private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4;
202 
203     private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 100;
204 
205     private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1);
206     private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2);
207     private static final Duration PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT = Duration.ofSeconds(10);
208 
209     static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission";
210     static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = "message_access_permission";
211     static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission";
212 
213     private static BluetoothProperties.snoop_log_mode_values sSnoopLogSettingAtEnable =
214             BluetoothProperties.snoop_log_mode_values.EMPTY;
215     private static String sDefaultSnoopLogSettingAtEnable = "empty";
216     private static boolean sSnoopLogFilterHeadersSettingAtEnable = false;
217     private static boolean sSnoopLogFilterProfileA2dpSettingAtEnable = false;
218     private static boolean sSnoopLogFilterProfileRfcommSettingAtEnable = false;
219 
220     private static BluetoothProperties.snoop_log_filter_profile_pbap_values
221             sSnoopLogFilterProfilePbapModeSettingAtEnable =
222                     BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY;
223     private static BluetoothProperties.snoop_log_filter_profile_map_values
224             sSnoopLogFilterProfileMapModeSettingAtEnable =
225                     BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY;
226 
227     private static AdapterService sAdapterService;
228 
229     private final Object mEnergyInfoLock = new Object();
230     private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>();
231 
232     private final Map<Integer, ProfileService> mStartedProfiles = new HashMap<>();
233     private final List<ProfileService> mRegisteredProfiles = new ArrayList<>();
234     private final List<ProfileService> mRunningProfiles = new ArrayList<>();
235 
236     private final List<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>();
237 
238     private final AdapterNativeInterface mNativeInterface = AdapterNativeInterface.getInstance();
239 
240     private final Map<BluetoothDevice, RemoteCallbackList<IBluetoothMetadataListener>>
241             mMetadataListeners = new HashMap<>();
242 
243     // Map<groupId, PendingAudioProfilePreferenceRequest>
244     @GuardedBy("mCsipGroupsPendingAudioProfileChanges")
245     private final Map<Integer, PendingAudioProfilePreferenceRequest>
246             mCsipGroupsPendingAudioProfileChanges = new HashMap<>();
247 
248     private final Map<BluetoothStateCallback, Executor> mLocalCallbacks = new ConcurrentHashMap<>();
249     private final Map<UUID, RfcommListenerData> mBluetoothServerSockets = new ConcurrentHashMap<>();
250     private final ArrayDeque<IBluetoothOobDataCallback> mOobDataCallbackQueue = new ArrayDeque<>();
251 
252     private final RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback>
253             mPreferredAudioProfilesCallbacks = new RemoteCallbackList<>();
254     private final RemoteCallbackList<IBluetoothQualityReportReadyCallback>
255             mBluetoothQualityReportReadyCallbacks = new RemoteCallbackList<>();
256     private final RemoteCallbackList<IBluetoothCallback> mSystemServerCallbacks =
257             new RemoteCallbackList<>();
258     private final RemoteCallbackList<IBluetoothConnectionCallback> mBluetoothConnectionCallbacks =
259             new RemoteCallbackList<>();
260 
261     private final BluetoothEventLogger mScanModeChanges =
262             new BluetoothEventLogger(10, "Scan Mode Changes");
263 
264     private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener();
265 
266     private final BluetoothHciVendorSpecificDispatcher mBluetoothHciVendorSpecificDispatcher =
267             new BluetoothHciVendorSpecificDispatcher();
268 
269     private final Looper mLooper;
270     private final AdapterServiceHandler mHandler;
271 
272     private int mStackReportedState;
273     private long mTxTimeTotalMs;
274     private long mRxTimeTotalMs;
275     private long mIdleTimeTotalMs;
276     private long mEnergyUsedTotalVoltAmpSecMicro;
277     private final HashSet<String> mLeAudioAllowDevices = new HashSet<>();
278 
279     /* List of pairs of gatt clients which controls AutoActiveMode on the device.*/
280     @VisibleForTesting
281     final List<Pair<Integer, BluetoothDevice>> mLeGattClientsControllingAutoActiveMode =
282             new ArrayList<>();
283 
284     private BluetoothAdapter mAdapter;
285     private AdapterProperties mAdapterProperties;
286     private AdapterState mAdapterStateMachine;
287     private BondStateMachine mBondStateMachine;
288     private RemoteDevices mRemoteDevices;
289     private AdapterSuspend mAdapterSuspend;
290 
291     /* TODO: Consider to remove the search API from this class, if changed to use call-back */
292     private SdpManager mSdpManager = null;
293 
294     private boolean mNativeAvailable;
295     private boolean mCleaningUp;
296     private boolean mQuietmode = false;
297     private final Map<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>();
298 
299     private BatteryStatsManager mBatteryStatsManager;
300     private PowerManager mPowerManager;
301     private PowerManager.WakeLock mWakeLock;
302     private UserManager mUserManager;
303     private CompanionDeviceManager mCompanionDeviceManager;
304 
305     // Phone Policy is not used on all devices and can be empty
306     private Optional<PhonePolicy> mPhonePolicy = Optional.empty();
307 
308     private ActiveDeviceManager mActiveDeviceManager;
309     private final DatabaseManager mDatabaseManager;
310     private final SilenceDeviceManager mSilenceDeviceManager;
311     private CompanionManager mBtCompanionManager;
312     private AppOpsManager mAppOps;
313 
314     private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder;
315 
316     private BluetoothKeystoreService mBluetoothKeystoreService;
317     private HeadsetService mHeadsetService;
318     private HeadsetClientService mHeadsetClientService;
319     private A2dpService mA2dpService;
320     private A2dpSinkService mA2dpSinkService;
321     private BluetoothMapService mMapService;
322     private MapClientService mMapClientService;
323     private HidDeviceService mHidDeviceService;
324     private HidHostService mHidHostService;
325     private PanService mPanService;
326     private BluetoothPbapService mPbapService;
327     private PbapClientService mPbapClientService;
328     private HearingAidService mHearingAidService;
329     private HapClientService mHapClientService;
330     private SapService mSapService;
331     private VolumeControlService mVolumeControlService;
332     private CsipSetCoordinatorService mCsipSetCoordinatorService;
333     private LeAudioService mLeAudioService;
334     private BassClientService mBassClientService;
335     private BatteryService mBatteryService;
336     private BluetoothQualityReportNativeInterface mBluetoothQualityReportNativeInterface;
337     private BluetoothHciVendorSpecificNativeInterface mBluetoothHciVendorSpecificNativeInterface;
338     private GattService mGattService;
339     private ScanController mScanController;
340 
341     private volatile boolean mTestModeEnabled = false;
342 
343     /** Handlers for incoming service calls */
344     private AdapterServiceBinder mBinder;
345 
346     private volatile int mScanMode;
347 
348     // Report ID definition
349     public enum BqrQualityReportId {
350         QUALITY_REPORT_ID_MONITOR_MODE(0x01),
351         QUALITY_REPORT_ID_APPROACH_LSTO(0x02),
352         QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY(0x03),
353         QUALITY_REPORT_ID_SCO_VOICE_CHOPPY(0x04),
354         QUALITY_REPORT_ID_ROOT_INFLAMMATION(0x05),
355         QUALITY_REPORT_ID_CONNECT_FAIL(0x08),
356         QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE(0x11),
357         QUALITY_REPORT_ID_BT_SCHEDULING_TRACE(0x12),
358         QUALITY_REPORT_ID_CONTROLLER_DBG_INFO(0x13);
359 
360         private final int mValue;
361 
BqrQualityReportId(int value)362         BqrQualityReportId(int value) {
363             mValue = value;
364         }
365 
getValue()366         public int getValue() {
367             return mValue;
368         }
369     };
370 
371     // Keep a constructor for ActivityThread.handleCreateService
AdapterService()372     AdapterService() {
373         this(Looper.getMainLooper());
374     }
375 
376     @VisibleForTesting
AdapterService(Context ctx)377     public AdapterService(Context ctx) {
378         this(Looper.getMainLooper(), ctx);
379     }
380 
381     @VisibleForTesting
AdapterService(Looper looper, Context ctx)382     AdapterService(Looper looper, Context ctx) {
383         this(looper);
384         attachBaseContext(ctx);
385     }
386 
AdapterService(Looper looper)387     private AdapterService(Looper looper) {
388         mLooper = requireNonNull(looper);
389         mHandler = new AdapterServiceHandler(mLooper);
390         mSilenceDeviceManager = new SilenceDeviceManager(this, new ServiceFactory(), mLooper);
391         mDatabaseManager = new DatabaseManager(this);
392     }
393 
getAdapterService()394     public static synchronized AdapterService getAdapterService() {
395         return sAdapterService;
396     }
397 
398     /** Allow test to set an AdapterService to be return by AdapterService.getAdapterService() */
399     @VisibleForTesting
setAdapterService(AdapterService instance)400     public static synchronized void setAdapterService(AdapterService instance) {
401         if (instance == null) {
402             Log.e(TAG, "setAdapterService() - instance is null");
403             return;
404         }
405         Log.d(TAG, "setAdapterService() - set service to " + instance);
406         sAdapterService = instance;
407     }
408 
409     /** Clear test Adapter service. See {@code setAdapterService} */
410     @VisibleForTesting
clearAdapterService(AdapterService instance)411     public static synchronized void clearAdapterService(AdapterService instance) {
412         if (sAdapterService == instance) {
413             Log.d(TAG, "clearAdapterService() - This adapter was cleared " + instance);
414             sAdapterService = null;
415         } else {
416             Log.d(
417                     TAG,
418                     "clearAdapterService() - incorrect cleared adapter."
419                             + (" Instance=" + instance)
420                             + (" vs sAdapterService=" + sAdapterService));
421         }
422     }
423 
424     /**
425      * Register a {@link ProfileService} with AdapterService.
426      *
427      * @param profile the service being added.
428      */
addProfile(ProfileService profile)429     public void addProfile(ProfileService profile) {
430         mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget();
431     }
432 
433     /**
434      * Unregister a ProfileService with AdapterService.
435      *
436      * @param profile the service being removed.
437      */
removeProfile(ProfileService profile)438     public void removeProfile(ProfileService profile) {
439         mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget();
440     }
441 
442     /**
443      * Notify AdapterService that a ProfileService has started or stopped.
444      *
445      * @param profile the service being removed.
446      * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF}
447      */
onProfileServiceStateChanged(ProfileService profile, int state)448     public void onProfileServiceStateChanged(ProfileService profile, int state) {
449         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
450             throw new IllegalArgumentException(nameForState(state));
451         }
452         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
453         m.obj = profile;
454         m.arg1 = state;
455         mHandler.sendMessage(m);
456     }
457 
458     class AdapterServiceHandler extends Handler {
AdapterServiceHandler(Looper looper)459         AdapterServiceHandler(Looper looper) {
460             super(looper);
461         }
462 
463         @Override
handleMessage(Message msg)464         public void handleMessage(Message msg) {
465             Log.v(TAG, "handleMessage() - Message: " + msg.what);
466 
467             switch (msg.what) {
468                 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:
469                     Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
470                     processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);
471                     break;
472                 case MESSAGE_PROFILE_SERVICE_REGISTERED:
473                     Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED");
474                     registerProfileService((ProfileService) msg.obj);
475                     break;
476                 case MESSAGE_PROFILE_SERVICE_UNREGISTERED:
477                     Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
478                     unregisterProfileService((ProfileService) msg.obj);
479                     break;
480                 case MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT:
481                     Log.e(
482                             TAG,
483                             "handleMessage() - "
484                                     + "MESSAGE_PREFERRED_PROFILE_CHANGE_AUDIO_FRAMEWORK_TIMEOUT");
485                     int groupId = (int) msg.obj;
486 
487                     synchronized (mCsipGroupsPendingAudioProfileChanges) {
488                         removeFromPendingAudioProfileChanges(groupId);
489                         PendingAudioProfilePreferenceRequest request =
490                                 mCsipGroupsPendingAudioProfileChanges.remove(groupId);
491                         Log.e(
492                                 TAG,
493                                 "Preferred audio profiles change audio framework timeout for "
494                                         + ("device " + request.device));
495                         sendPreferredAudioProfilesCallbackToApps(
496                                 request.device,
497                                 request.preferences,
498                                 BluetoothStatusCodes.ERROR_TIMEOUT);
499                     }
500                     break;
501             }
502         }
503 
registerProfileService(ProfileService profile)504         private void registerProfileService(ProfileService profile) {
505             if (mRegisteredProfiles.contains(profile)) {
506                 Log.e(TAG, profile.getName() + " already registered.");
507                 return;
508             }
509             mRegisteredProfiles.add(profile);
510         }
511 
unregisterProfileService(ProfileService profile)512         private void unregisterProfileService(ProfileService profile) {
513             if (!mRegisteredProfiles.contains(profile)) {
514                 Log.e(TAG, profile.getName() + " not registered (UNREGISTER).");
515                 return;
516             }
517             mRegisteredProfiles.remove(profile);
518         }
519 
processProfileServiceStateChanged(ProfileService profile, int state)520         private void processProfileServiceStateChanged(ProfileService profile, int state) {
521             switch (state) {
522                 case BluetoothAdapter.STATE_ON:
523                     if (!mRegisteredProfiles.contains(profile)) {
524                         Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
525                         return;
526                     }
527                     if (mRunningProfiles.contains(profile)) {
528                         Log.e(TAG, profile.getName() + " already running.");
529                         return;
530                     }
531                     mRunningProfiles.add(profile);
532                     // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware
533                     // initialization. Configuring a device without GATT causes start up failures.
534                     if (GattService.class.getSimpleName().equals(profile.getName())
535                             && !Flags.onlyStartScanDuringBleOn()) {
536                         mNativeInterface.enable();
537                     } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
538                             && mRegisteredProfiles.size() == mRunningProfiles.size()) {
539                         mAdapterProperties.onBluetoothReady();
540                         setScanMode(SCAN_MODE_CONNECTABLE, "processProfileServiceStateChanged");
541                         updateUuids();
542                         initProfileServices();
543                         mNativeInterface.getAdapterProperty(
544                                 AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER);
545                         mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
546                         mBtCompanionManager.loadCompanionInfo();
547                     }
548                     break;
549                 case BluetoothAdapter.STATE_OFF:
550                     if (!mRegisteredProfiles.contains(profile)) {
551                         Log.e(TAG, profile.getName() + " not registered (STATE_OFF).");
552                         return;
553                     }
554                     if (!mRunningProfiles.contains(profile)) {
555                         Log.e(TAG, profile.getName() + " not running.");
556                         return;
557                     }
558                     mRunningProfiles.remove(profile);
559 
560                     if (Flags.onlyStartScanDuringBleOn()) {
561                         if (mRunningProfiles.size() == 0) {
562                             mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
563                         }
564                     } else {
565                         // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the
566                         // only profile available in the "BLE ON" state. If only GATT is left, send
567                         // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware.
568                         if ((mRunningProfiles.size() == 1
569                                 && (GattService.class
570                                         .getSimpleName()
571                                         .equals(mRunningProfiles.get(0).getName())))) {
572                             mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
573                         } else if (mRunningProfiles.size() == 0) {
574                             mNativeInterface.disable();
575                         }
576                     }
577                     break;
578                 default:
579                     Log.e(TAG, "Unhandled profile state: " + state);
580             }
581         }
582     }
583 
584     /**
585      * Stores information about requests made to the audio framework arising from calls to {@link
586      * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)}.
587      */
PendingAudioProfilePreferenceRequest( Bundle preferences, int numberOfRemainingRequestsToAudioFramework, BluetoothDevice device)588     private record PendingAudioProfilePreferenceRequest(
589             // The newly requested preferences
590             Bundle preferences,
591             // Reference counter for how many calls are pending completion in the audio framework
592             int numberOfRemainingRequestsToAudioFramework,
593             // The device with which the request was made. Used for sending the callback.
594             BluetoothDevice device) {}
595 
getNonNullSystemService(@onNull Class<T> clazz)596     final @NonNull <T> T getNonNullSystemService(@NonNull Class<T> clazz) {
597         return requireNonNull(getSystemService(clazz));
598     }
599 
600     @Override
onCreate()601     public void onCreate() {
602         super.onCreate();
603         Log.d(TAG, "onCreate()");
604         // OnCreate must perform the minimum of infallible and mandatory initialization
605         mRemoteDevices = new RemoteDevices(this, mLooper);
606         mAdapterProperties = new AdapterProperties(this, mRemoteDevices, mLooper);
607         mAdapterStateMachine = new AdapterState(this, mLooper);
608         mBinder = new AdapterServiceBinder(this);
609         mUserManager = getNonNullSystemService(UserManager.class);
610         mAppOps = getNonNullSystemService(AppOpsManager.class);
611         mPowerManager = getNonNullSystemService(PowerManager.class);
612         mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class);
613         mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class);
614         setAdapterService(this);
615     }
616 
617     @SuppressLint("AndroidFrameworkRequiresPermission")
init()618     private void init() {
619         Log.d(TAG, "init()");
620         Config.init(this);
621         mDeviceConfigListener.start();
622 
623         MetricsLogger.getInstance().init(this, mRemoteDevices);
624 
625         clearDiscoveringPackages();
626         mAdapter = BluetoothAdapter.getDefaultAdapter();
627         boolean isCommonCriteriaMode =
628                 getNonNullSystemService(DevicePolicyManager.class)
629                         .isCommonCriteriaModeEnabled(null);
630         mBluetoothKeystoreService =
631                 new BluetoothKeystoreService(
632                         BluetoothKeystoreNativeInterface.getInstance(), isCommonCriteriaMode);
633         mBluetoothKeystoreService.start();
634         int configCompareResult = mBluetoothKeystoreService.getCompareResult();
635 
636         // Start tracking Binder latency for the bluetooth process.
637         BluetoothFrameworkInitializer.initializeBinderCallsStats(getApplicationContext());
638 
639         // Android TV doesn't show consent dialogs for just works and encryption only le pairing
640         boolean isAtvDevice =
641                 getApplicationContext()
642                         .getPackageManager()
643                         .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
644         if (Utils.isInstrumentationTestMode()) {
645             Log.w(TAG, "This Bluetooth App is instrumented. ** Skip loading the native **");
646         } else {
647             Log.d(TAG, "Loading JNI Library");
648             System.loadLibrary("bluetooth_jni");
649         }
650         mNativeInterface.init(
651                 this,
652                 mAdapterProperties,
653                 mUserManager.isGuestUser(),
654                 isCommonCriteriaMode,
655                 configCompareResult,
656                 isAtvDevice);
657         mNativeAvailable = true;
658         // Load the name and address
659         mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDADDR);
660         mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDNAME);
661         mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE);
662 
663         mBluetoothKeystoreService.initJni();
664 
665         mBluetoothQualityReportNativeInterface =
666                 requireNonNull(BluetoothQualityReportNativeInterface.getInstance());
667         mBluetoothQualityReportNativeInterface.init();
668 
669         if (Flags.hciVendorSpecificExtension()) {
670             mBluetoothHciVendorSpecificNativeInterface =
671                     requireNonNull(mBluetoothHciVendorSpecificNativeInterface.getInstance());
672             mBluetoothHciVendorSpecificNativeInterface.init(mBluetoothHciVendorSpecificDispatcher);
673         }
674 
675         mSdpManager = new SdpManager(this, mLooper);
676 
677         mDatabaseManager.start(MetadataDatabase.createDatabase(this));
678 
679         boolean isAutomotiveDevice =
680                 getApplicationContext()
681                         .getPackageManager()
682                         .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
683 
684         /*
685          * Phone policy is specific to phone implementations and hence if a device wants to exclude
686          * it out then it can be disabled by using the flag below. Phone policy is never used on
687          * Android Automotive OS builds, in favor of a policy currently located in
688          * CarBluetoothService.
689          */
690         if (!isAutomotiveDevice && getResources().getBoolean(R.bool.enable_phone_policy)) {
691             Log.i(TAG, "Phone policy enabled");
692             mPhonePolicy = Optional.of(new PhonePolicy(this, mLooper, new ServiceFactory()));
693         } else {
694             Log.i(TAG, "Phone policy disabled");
695         }
696 
697         mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory());
698         mActiveDeviceManager.start();
699 
700         mBtCompanionManager = new CompanionManager(this, new ServiceFactory());
701 
702         mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this);
703 
704         if (Flags.adapterSuspendMgmt() && isAtLeastV()) {
705             mAdapterSuspend =
706                     new AdapterSuspend(
707                             mNativeInterface, mLooper, getSystemService(DeviceStateManager.class));
708         }
709 
710         invalidateBluetoothCaches();
711 
712         // First call to getSharedPreferences will result in a file read into
713         // memory cache. Call it here asynchronously to avoid potential ANR
714         // in the future
715         new AsyncTask<Void, Void, Void>() {
716             @Override
717             protected Void doInBackground(Void... params) {
718                 getSharedPreferences(
719                         PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
720                 getSharedPreferences(
721                         MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
722                 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
723                 return null;
724             }
725         }.execute();
726 
727         try {
728             int systemUiUid =
729                     getApplicationContext()
730                             .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0)
731                             .getPackageManager()
732                             .getPackageUid(
733                                     "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY);
734 
735             Utils.setSystemUiUid(systemUiUid);
736         } catch (PackageManager.NameNotFoundException e) {
737             // Some platforms, such as wearables do not have a system ui.
738             Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
739         }
740     }
741 
742     @Override
onBind(Intent intent)743     public IBinder onBind(Intent intent) {
744         Log.d(TAG, "onBind()");
745         return mBinder;
746     }
747 
748     @Override
onUnbind(Intent intent)749     public boolean onUnbind(Intent intent) {
750         Log.d(TAG, "onUnbind()");
751         return super.onUnbind(intent);
752     }
753 
754     @Override
onDestroy()755     public void onDestroy() {
756         Log.d(TAG, "onDestroy()");
757     }
758 
getActiveDeviceManager()759     public ActiveDeviceManager getActiveDeviceManager() {
760         return mActiveDeviceManager;
761     }
762 
getRemoteDevices()763     public RemoteDevices getRemoteDevices() {
764         return mRemoteDevices;
765     }
766 
getSilenceDeviceManager()767     public SilenceDeviceManager getSilenceDeviceManager() {
768         return mSilenceDeviceManager;
769     }
770 
getNative()771     AdapterNativeInterface getNative() {
772         return mNativeInterface;
773     }
774 
getHandler()775     AdapterServiceHandler getHandler() {
776         return mHandler;
777     }
778 
getDatabaseManager()779     DatabaseManager getDatabaseManager() {
780         return mDatabaseManager;
781     }
782 
getAdapterProperties()783     AdapterProperties getAdapterProperties() {
784         return mAdapterProperties;
785     }
786 
getMetadataListeners()787     Map<BluetoothDevice, RemoteCallbackList<IBluetoothMetadataListener>> getMetadataListeners() {
788         return mMetadataListeners;
789     }
790 
getBondAttemptCallerInfo()791     Map<String, CallerInfo> getBondAttemptCallerInfo() {
792         return mBondAttemptCallerInfo;
793     }
794 
getPhonePolicy()795     Optional<PhonePolicy> getPhonePolicy() {
796         return mPhonePolicy;
797     }
798 
getBondStateMachine()799     BondStateMachine getBondStateMachine() {
800         return mBondStateMachine;
801     }
802 
getCompanionDeviceManager()803     CompanionDeviceManager getCompanionDeviceManager() {
804         return mCompanionDeviceManager;
805     }
806 
getBluetoothSocketManagerBinder()807     BluetoothSocketManagerBinder getBluetoothSocketManagerBinder() {
808         return mBluetoothSocketManagerBinder;
809     }
810 
getBluetoothConnectionCallbacks()811     RemoteCallbackList<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() {
812         return mBluetoothConnectionCallbacks;
813     }
814 
815     RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback>
getPreferredAudioProfilesCallbacks()816             getPreferredAudioProfilesCallbacks() {
817         return mPreferredAudioProfilesCallbacks;
818     }
819 
820     RemoteCallbackList<IBluetoothQualityReportReadyCallback>
getBluetoothQualityReportReadyCallbacks()821             getBluetoothQualityReportReadyCallbacks() {
822         return mBluetoothQualityReportReadyCallbacks;
823     }
824 
getBluetoothHciVendorSpecificDispatcher()825     BluetoothHciVendorSpecificDispatcher getBluetoothHciVendorSpecificDispatcher() {
826         return mBluetoothHciVendorSpecificDispatcher;
827     }
828 
getBluetoothHciVendorSpecificNativeInterface()829     BluetoothHciVendorSpecificNativeInterface getBluetoothHciVendorSpecificNativeInterface() {
830         return mBluetoothHciVendorSpecificNativeInterface;
831     }
832 
833     /**
834      * Log L2CAP CoC Server Connection Metrics
835      *
836      * @param port port of socket
837      * @param isSecured if secured API is called
838      * @param result transaction result of the connection
839      * @param socketCreationLatencyMillis latency of the connection
840      * @param timeoutMillis timeout set by the app
841      */
logL2capcocServerConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis, long timeoutMillis, int appUid)842     public void logL2capcocServerConnection(
843             BluetoothDevice device,
844             int port,
845             boolean isSecured,
846             int result,
847             long socketCreationTimeMillis,
848             long socketCreationLatencyMillis,
849             long socketConnectionTimeMillis,
850             long timeoutMillis,
851             int appUid) {
852 
853         int metricId = 0;
854         if (device != null) {
855             metricId = getMetricId(device);
856         }
857         long currentTime = System.currentTimeMillis();
858         long endToEndLatencyMillis = currentTime - socketCreationTimeMillis;
859         long socketAcceptanceLatencyMillis = currentTime - socketConnectionTimeMillis;
860         Log.i(
861                 TAG,
862                 "Statslog L2capcoc server connection."
863                         + (" metricId " + metricId)
864                         + (" port " + port)
865                         + (" isSecured " + isSecured)
866                         + (" result " + result)
867                         + (" endToEndLatencyMillis " + endToEndLatencyMillis)
868                         + (" socketCreationLatencyMillis " + socketCreationLatencyMillis)
869                         + (" socketAcceptanceLatencyMillis " + socketAcceptanceLatencyMillis)
870                         + (" timeout set by app " + timeoutMillis)
871                         + (" appUid " + appUid));
872         BluetoothStatsLog.write(
873                 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_SERVER_CONNECTION,
874                 metricId,
875                 port,
876                 isSecured,
877                 result,
878                 endToEndLatencyMillis,
879                 timeoutMillis,
880                 appUid,
881                 socketCreationLatencyMillis,
882                 socketAcceptanceLatencyMillis);
883     }
884 
885     /**
886      * Log L2CAP CoC Client Connection Metrics
887      *
888      * @param device Bluetooth device
889      * @param port port of socket
890      * @param isSecured if secured API is called
891      * @param result transaction result of the connection
892      * @param socketCreationLatencyNanos latency of the connection
893      */
logL2capcocClientConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeNanos, long socketCreationLatencyNanos, long socketConnectionTimeNanos, int appUid)894     public void logL2capcocClientConnection(
895             BluetoothDevice device,
896             int port,
897             boolean isSecured,
898             int result,
899             long socketCreationTimeNanos,
900             long socketCreationLatencyNanos,
901             long socketConnectionTimeNanos,
902             int appUid) {
903 
904         int metricId = getMetricId(device);
905         long currentTime = System.nanoTime();
906         long endToEndLatencyMillis = (currentTime - socketCreationTimeNanos) / 1000000;
907         long socketCreationLatencyMillis = socketCreationLatencyNanos / 1000000;
908         long socketConnectionLatencyMillis = (currentTime - socketConnectionTimeNanos) / 1000000;
909         Log.i(
910                 TAG,
911                 "Statslog L2capcoc client connection."
912                         + (" metricId " + metricId)
913                         + (" port " + port)
914                         + (" isSecured " + isSecured)
915                         + (" result " + result)
916                         + (" endToEndLatencyMillis " + endToEndLatencyMillis)
917                         + (" socketCreationLatencyMillis " + socketCreationLatencyMillis)
918                         + (" socketConnectionLatencyMillis " + socketConnectionLatencyMillis)
919                         + (" appUid " + appUid));
920         BluetoothStatsLog.write(
921                 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION,
922                 metricId,
923                 port,
924                 isSecured,
925                 result,
926                 endToEndLatencyMillis,
927                 appUid,
928                 socketCreationLatencyMillis,
929                 socketConnectionLatencyMillis);
930     }
931 
932     /**
933      * Log RFCOMM Connection Metrics
934      *
935      * @param device Bluetooth device
936      * @param isSecured if secured API is called
937      * @param resultCode transaction result of the connection
938      * @param isSerialPort true if service class UUID is 0x1101
939      */
logRfcommConnectionAttempt( BluetoothDevice device, boolean isSecured, int resultCode, long socketCreationTimeNanos, boolean isSerialPort, int appUid)940     public void logRfcommConnectionAttempt(
941             BluetoothDevice device,
942             boolean isSecured,
943             int resultCode,
944             long socketCreationTimeNanos,
945             boolean isSerialPort,
946             int appUid) {
947         int metricId = getMetricId(device);
948         long currentTime = System.nanoTime();
949         long endToEndLatencyNanos = currentTime - socketCreationTimeNanos;
950         byte[] remoteDeviceInfoBytes = MetricsLogger.getInstance().getRemoteDeviceInfoProto(device);
951         BluetoothStatsLog.write(
952                 BluetoothStatsLog.BLUETOOTH_RFCOMM_CONNECTION_ATTEMPTED,
953                 metricId,
954                 endToEndLatencyNanos,
955                 isSecured
956                         ? BluetoothRfcommProtoEnums.SOCKET_SECURITY_SECURE
957                         : BluetoothRfcommProtoEnums.SOCKET_SECURITY_INSECURE,
958                 resultCode,
959                 isSerialPort,
960                 appUid,
961                 remoteDeviceInfoBytes);
962     }
963 
sdpSearch(BluetoothDevice device, ParcelUuid uuid)964     public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) {
965         if (mSdpManager == null) {
966             return false;
967         }
968         mSdpManager.sdpSearch(device, uuid);
969         return true;
970     }
971 
972     @RequiresPermission(BLUETOOTH_CONNECT)
bringUpBle()973     void bringUpBle() {
974         Log.d(TAG, "bleOnProcessStart()");
975 
976         if (getResources()
977                 .getBoolean(R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
978             Config.init(getApplicationContext());
979         }
980 
981         // Reset |mRemoteDevices| whenever BLE is turned off then on
982         // This is to replace the fact that |mRemoteDevices| was
983         // reinitialized in previous code.
984         //
985         // TODO(apanicke): The reason is unclear but
986         // I believe it is to clear the variable every time BLE was
987         // turned off then on. The same effect can be achieved by
988         // calling cleanup but this may not be necessary at all
989         // We should figure out why this is needed later
990         mRemoteDevices.reset();
991         mAdapterProperties.init();
992 
993         Log.d(TAG, "bleOnProcessStart() - Make Bond State Machine");
994         mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
995 
996         mNativeInterface.getCallbacks().init(mBondStateMachine, mRemoteDevices);
997 
998         mBatteryStatsManager.reportBleScanReset();
999         BluetoothStatsLog.write_non_chained(
1000                 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED,
1001                 -1,
1002                 null,
1003                 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET,
1004                 false,
1005                 false,
1006                 false);
1007 
1008         // TODO(b/228875190): GATT is assumed supported. As a result, we don't respect the
1009         // configuration sysprop. Configuring a device without GATT, although rare, will cause stack
1010         // start up errors yielding init loops.
1011         if (!GattService.isEnabled()) {
1012             Log.w(
1013                     TAG,
1014                     "GATT is configured off but the stack assumes it to be enabled. Start anyway.");
1015         }
1016         if (Flags.onlyStartScanDuringBleOn()) {
1017             startScanController();
1018         } else {
1019             startGattProfileService();
1020         }
1021     }
1022 
bringDownBle()1023     void bringDownBle() {
1024         if (Flags.onlyStartScanDuringBleOn()) {
1025             stopScanController();
1026         } else {
1027             stopGattProfileService();
1028         }
1029     }
1030 
stateChangeCallback(int status)1031     void stateChangeCallback(int status) {
1032         if (status == AbstractionLayer.BT_STATE_OFF) {
1033             Log.d(TAG, "stateChangeCallback: disableNative() completed");
1034             mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
1035         } else if (status == AbstractionLayer.BT_STATE_ON) {
1036             mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED);
1037         } else {
1038             Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback");
1039         }
1040     }
1041 
startProfileServices()1042     void startProfileServices() {
1043         Log.d(TAG, "startCoreServices()");
1044         int[] supportedProfileServices = Config.getSupportedProfiles();
1045         if (Flags.onlyStartScanDuringBleOn()) {
1046             // Scanning is always supported, started separately, and is not a profile service.
1047             // This will check other profile services.
1048             if (supportedProfileServices.length == 0) {
1049                 mAdapterProperties.onBluetoothReady();
1050                 setScanMode(SCAN_MODE_CONNECTABLE, "startProfileServices");
1051                 updateUuids();
1052                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
1053             } else {
1054                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
1055             }
1056         } else {
1057             // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then
1058             // just move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause
1059             // adapter initialization failures
1060             if (supportedProfileServices.length == 1
1061                     && supportedProfileServices[0] == BluetoothProfile.GATT) {
1062                 mAdapterProperties.onBluetoothReady();
1063                 setScanMode(SCAN_MODE_CONNECTABLE, "startProfileServices");
1064                 updateUuids();
1065                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
1066             } else {
1067                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
1068             }
1069         }
1070     }
1071 
stopProfileServices()1072     void stopProfileServices() {
1073         // Make sure to stop classic background tasks now
1074         mNativeInterface.cancelDiscovery();
1075         setScanMode(SCAN_MODE_NONE, "StopProfileServices");
1076 
1077         int[] supportedProfileServices = Config.getSupportedProfiles();
1078         if (Flags.onlyStartScanDuringBleOn()) {
1079             // Scanning is always supported, started separately, and is not a profile service.
1080             // This will check other profile services.
1081             if (supportedProfileServices.length == 0) {
1082                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
1083             } else {
1084                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF);
1085             }
1086         } else {
1087             // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just
1088             // move on to BREDR_STOPPED
1089             if (supportedProfileServices.length == 1
1090                     && (mRunningProfiles.size() == 1
1091                             && GattService.class
1092                                     .getSimpleName()
1093                                     .equals(mRunningProfiles.get(0).getName()))) {
1094                 Log.d(
1095                         TAG,
1096                         "stopProfileServices() - No profiles services to stop or already stopped.");
1097                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
1098             } else {
1099                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF);
1100             }
1101         }
1102     }
1103 
startGattProfileService()1104     private void startGattProfileService() {
1105         Log.i(TAG, "startGattProfileService() called");
1106         mGattService = new GattService(this);
1107 
1108         mStartedProfiles.put(BluetoothProfile.GATT, mGattService);
1109         addProfile(mGattService);
1110         mGattService.setAvailable(true);
1111         onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_ON);
1112     }
1113 
startScanController()1114     private void startScanController() {
1115         Log.i(TAG, "startScanController() called");
1116         mScanController = new ScanController(this);
1117         mNativeInterface.enable();
1118     }
1119 
stopGattProfileService()1120     private void stopGattProfileService() {
1121         Log.i(TAG, "stopGattProfileService() called");
1122         setScanMode(SCAN_MODE_NONE, "stopGattProfileService");
1123 
1124         if (mRunningProfiles.size() == 0) {
1125             Log.d(TAG, "stopGattProfileService() - No profiles services to stop.");
1126             mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
1127         }
1128 
1129         mStartedProfiles.remove(BluetoothProfile.GATT);
1130         if (mGattService != null) {
1131             mGattService.setAvailable(false);
1132             onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_OFF);
1133             removeProfile(mGattService);
1134             mGattService.cleanup();
1135             mGattService.getBinder().cleanup();
1136             mGattService = null;
1137         }
1138     }
1139 
stopScanController()1140     private void stopScanController() {
1141         Log.i(TAG, "stopScanController() called");
1142         setScanMode(SCAN_MODE_NONE, "stopScanController");
1143 
1144         if (mScanController == null) {
1145             mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
1146         } else {
1147             mScanController.cleanup();
1148             mScanController = null;
1149             mNativeInterface.disable();
1150         }
1151     }
1152 
updateLeAudioProfileServiceState()1153     void updateLeAudioProfileServiceState() {
1154         Set<Integer> nonSupportedProfiles = new HashSet<>();
1155 
1156         if (!isLeConnectedIsochronousStreamCentralSupported()) {
1157             for (int profileId : Config.getLeAudioUnicastProfiles()) {
1158                 nonSupportedProfiles.add(profileId);
1159             }
1160         }
1161 
1162         if (!isLeAudioBroadcastAssistantSupported()) {
1163             nonSupportedProfiles.add(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
1164         }
1165 
1166         if (!isLeAudioBroadcastSourceSupported()) {
1167             Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false);
1168         }
1169 
1170         // Disable the non-supported profiles service
1171         for (int profileId : nonSupportedProfiles) {
1172             Config.setProfileEnabled(profileId, false);
1173             if (mStartedProfiles.containsKey(profileId)) {
1174                 setProfileServiceState(profileId, BluetoothAdapter.STATE_OFF);
1175             }
1176         }
1177     }
1178 
broadcastToSystemServerCallbacks( String logAction, RemoteExceptionIgnoringConsumer<IBluetoothCallback> action)1179     private void broadcastToSystemServerCallbacks(
1180             String logAction, RemoteExceptionIgnoringConsumer<IBluetoothCallback> action) {
1181         final int itemCount = mSystemServerCallbacks.beginBroadcast();
1182         Log.d(TAG, "Broadcasting [" + logAction + "] to " + itemCount + " receivers.");
1183         for (int i = 0; i < itemCount; i++) {
1184             action.accept(mSystemServerCallbacks.getBroadcastItem(i));
1185         }
1186         mSystemServerCallbacks.finishBroadcast();
1187     }
1188 
updateAdapterName(String name)1189     void updateAdapterName(String name) {
1190         broadcastToSystemServerCallbacks(
1191                 "updateAdapterName(" + name + ")", (c) -> c.onAdapterNameChange(name));
1192     }
1193 
updateAdapterAddress(String address)1194     void updateAdapterAddress(String address) {
1195         broadcastToSystemServerCallbacks(
1196                 "updateAdapterAddress(" + BluetoothUtils.toAnonymizedAddress(address) + ")",
1197                 (c) -> c.onAdapterAddressChange(address));
1198     }
1199 
updateAdapterState(int from, int to)1200     void updateAdapterState(int from, int to) {
1201         mAdapterProperties.setState(to);
1202 
1203         broadcastToSystemServerCallbacks(
1204                 "updateAdapterState(" + nameForState(from) + ", " + nameForState(to) + ")",
1205                 (c) -> c.onBluetoothStateChange(from, to));
1206 
1207         for (Map.Entry<BluetoothStateCallback, Executor> e : mLocalCallbacks.entrySet()) {
1208             e.getValue().execute(() -> e.getKey().onBluetoothStateChange(from, to));
1209         }
1210 
1211         // Turn the Adapter all the way off if we are disabling and the snoop log setting changed.
1212         if (to == BluetoothAdapter.STATE_BLE_TURNING_ON) {
1213             sSnoopLogSettingAtEnable =
1214                     BluetoothProperties.snoop_log_mode()
1215                             .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY);
1216             sDefaultSnoopLogSettingAtEnable =
1217                     Settings.Global.getString(
1218                             getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
1219 
1220             sSnoopLogFilterHeadersSettingAtEnable =
1221                     BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false);
1222             sSnoopLogFilterProfileA2dpSettingAtEnable =
1223                     BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false);
1224             sSnoopLogFilterProfileRfcommSettingAtEnable =
1225                     BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false);
1226             sSnoopLogFilterProfilePbapModeSettingAtEnable =
1227                     BluetoothProperties.snoop_log_filter_profile_pbap()
1228                             .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY);
1229             sSnoopLogFilterProfileMapModeSettingAtEnable =
1230                     BluetoothProperties.snoop_log_filter_profile_map()
1231                             .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY);
1232 
1233             if (Utils.isInstrumentationTestMode()) {
1234                 return;
1235             }
1236             BluetoothProperties.snoop_default_mode(
1237                     BluetoothProperties.snoop_default_mode_values.DISABLED);
1238             for (BluetoothProperties.snoop_default_mode_values value :
1239                     BluetoothProperties.snoop_default_mode_values.values()) {
1240                 if (value.getPropValue().equals(sDefaultSnoopLogSettingAtEnable)) {
1241                     BluetoothProperties.snoop_default_mode(value);
1242                 }
1243             }
1244         } else if (to == BluetoothAdapter.STATE_BLE_ON && from != BluetoothAdapter.STATE_OFF) {
1245             var snoopLogSetting =
1246                     BluetoothProperties.snoop_log_mode()
1247                             .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY);
1248             var snoopDefaultModeSetting =
1249                     Settings.Global.getString(
1250                             getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
1251 
1252             var snoopLogFilterHeadersSettingAtEnable =
1253                     BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false);
1254             var snoopLogFilterProfileA2dpSettingAtEnable =
1255                     BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false);
1256             var snoopLogFilterProfileRfcommSettingAtEnable =
1257                     BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false);
1258 
1259             var snoopLogFilterProfilePbapModeSetting =
1260                     BluetoothProperties.snoop_log_filter_profile_pbap()
1261                             .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY);
1262             var snoopLogFilterProfileMapModeSetting =
1263                     BluetoothProperties.snoop_log_filter_profile_map()
1264                             .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY);
1265 
1266             if (!(sSnoopLogSettingAtEnable == snoopLogSetting)
1267                     || !(Objects.equals(sDefaultSnoopLogSettingAtEnable, snoopDefaultModeSetting))
1268                     || !(sSnoopLogFilterHeadersSettingAtEnable
1269                             == snoopLogFilterHeadersSettingAtEnable)
1270                     || !(sSnoopLogFilterProfileA2dpSettingAtEnable
1271                             == snoopLogFilterProfileA2dpSettingAtEnable)
1272                     || !(sSnoopLogFilterProfileRfcommSettingAtEnable
1273                             == snoopLogFilterProfileRfcommSettingAtEnable)
1274                     || !(sSnoopLogFilterProfilePbapModeSettingAtEnable
1275                             == snoopLogFilterProfilePbapModeSetting)
1276                     || !(sSnoopLogFilterProfileMapModeSettingAtEnable
1277                             == snoopLogFilterProfileMapModeSetting)) {
1278                 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
1279             }
1280         }
1281     }
1282 
linkQualityReportCallback( long timestamp, int reportId, int rssi, int snr, int retransmissionCount, int packetsNotReceiveCount, int negativeAcknowledgementCount)1283     void linkQualityReportCallback(
1284             long timestamp,
1285             int reportId,
1286             int rssi,
1287             int snr,
1288             int retransmissionCount,
1289             int packetsNotReceiveCount,
1290             int negativeAcknowledgementCount) {
1291         BluetoothInCallService bluetoothInCallService = BluetoothInCallService.getInstance();
1292 
1293         if (reportId == BqrQualityReportId.QUALITY_REPORT_ID_SCO_VOICE_CHOPPY.getValue()) {
1294             if (bluetoothInCallService == null) {
1295                 Log.w(
1296                         TAG,
1297                         "No BluetoothInCallService while trying to send BQR."
1298                                 + (" timestamp: " + timestamp)
1299                                 + (" reportId: " + reportId)
1300                                 + (" rssi: " + rssi)
1301                                 + (" snr: " + snr)
1302                                 + (" retransmissionCount: " + retransmissionCount)
1303                                 + (" packetsNotReceiveCount: " + packetsNotReceiveCount)
1304                                 + (" negativeAcknowledgementCount: "
1305                                         + negativeAcknowledgementCount));
1306                 return;
1307             }
1308             bluetoothInCallService.sendBluetoothCallQualityReport(
1309                     timestamp,
1310                     rssi,
1311                     snr,
1312                     retransmissionCount,
1313                     packetsNotReceiveCount,
1314                     negativeAcknowledgementCount);
1315         }
1316     }
1317 
1318     /**
1319      * Callback from Bluetooth Quality Report Native Interface to inform the listeners about
1320      * Bluetooth Quality.
1321      *
1322      * @param device is the BluetoothDevice which connection quality is being reported
1323      * @param bluetoothQualityReport a Parcel that contains information about Bluetooth Quality
1324      * @return whether the Bluetooth stack acknowledged the change successfully
1325      */
bluetoothQualityReportReadyCallback( BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport)1326     public int bluetoothQualityReportReadyCallback(
1327             BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport) {
1328         synchronized (mBluetoothQualityReportReadyCallbacks) {
1329             int n = mBluetoothQualityReportReadyCallbacks.beginBroadcast();
1330             Log.d(
1331                     TAG,
1332                     "bluetoothQualityReportReadyCallback() - "
1333                             + "Broadcasting Bluetooth Quality Report to "
1334                             + n
1335                             + " receivers.");
1336             for (int i = 0; i < n; i++) {
1337                 try {
1338                     mBluetoothQualityReportReadyCallbacks
1339                             .getBroadcastItem(i)
1340                             .onBluetoothQualityReportReady(
1341                                     device, bluetoothQualityReport, BluetoothStatusCodes.SUCCESS);
1342                 } catch (RemoteException e) {
1343                     Log.d(
1344                             TAG,
1345                             "bluetoothQualityReportReadyCallback() - Callback #"
1346                                     + i
1347                                     + " failed ("
1348                                     + e
1349                                     + ")");
1350                 }
1351             }
1352             mBluetoothQualityReportReadyCallbacks.finishBroadcast();
1353         }
1354 
1355         return BluetoothStatusCodes.SUCCESS;
1356     }
1357 
switchBufferSizeCallback(boolean isLowLatencyBufferSize)1358     void switchBufferSizeCallback(boolean isLowLatencyBufferSize) {
1359         List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP);
1360         if (activeDevices.size() != 1) {
1361             Log.e(
1362                     TAG,
1363                     "Cannot switch buffer size. The number of A2DP active devices is "
1364                             + activeDevices.size());
1365             return;
1366         }
1367 
1368         // Send intent to fastpair
1369         Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE);
1370         switchBufferSizeIntent.setClassName(
1371                 getString(com.android.bluetooth.R.string.peripheral_link_package),
1372                 getString(com.android.bluetooth.R.string.peripheral_link_package)
1373                         + getString(com.android.bluetooth.R.string.peripheral_link_service));
1374         switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, activeDevices.get(0));
1375         switchBufferSizeIntent.putExtra(
1376                 BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize);
1377         sendBroadcastMultiplePermissions(
1378                 switchBufferSizeIntent,
1379                 new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED},
1380                 null);
1381     }
1382 
switchCodecCallback(boolean isLowLatencyBufferSize)1383     void switchCodecCallback(boolean isLowLatencyBufferSize) {
1384         List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP);
1385         if (activeDevices.size() != 1) {
1386             Log.e(
1387                     TAG,
1388                     "Cannot switch buffer size. The number of A2DP active devices is "
1389                             + activeDevices.size());
1390             return;
1391         }
1392         mA2dpService.switchCodecByBufferSize(activeDevices.get(0), isLowLatencyBufferSize);
1393     }
1394 
1395     @RequiresPermission(BLUETOOTH_CONNECT)
cleanup()1396     void cleanup() {
1397         Log.d(TAG, "cleanup()");
1398         if (mCleaningUp) {
1399             Log.e(TAG, "cleanup() - Service already starting to cleanup, ignoring request...");
1400             return;
1401         }
1402 
1403         MetricsLogger.getInstance().close();
1404 
1405         clearAdapterService(this);
1406 
1407         mCleaningUp = true;
1408         invalidateBluetoothCaches();
1409 
1410         stopRfcommServerSockets();
1411 
1412         // This wake lock release may also be called concurrently by
1413         // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here.
1414         synchronized (this) {
1415             if (mWakeLock != null) {
1416                 if (mWakeLock.isHeld()) {
1417                     mWakeLock.release();
1418                 }
1419                 mWakeLock = null;
1420             }
1421         }
1422 
1423         mDatabaseManager.cleanup();
1424 
1425         if (mAdapterStateMachine != null) {
1426             mAdapterStateMachine.doQuit();
1427         }
1428 
1429         if (mBondStateMachine != null) {
1430             mBondStateMachine.doQuit();
1431         }
1432 
1433         if (mRemoteDevices != null) {
1434             mRemoteDevices.reset();
1435         }
1436 
1437         if (mSdpManager != null) {
1438             mSdpManager.cleanup();
1439             mSdpManager = null;
1440         }
1441 
1442         if (mNativeAvailable) {
1443             Log.d(TAG, "cleanup() - Cleaning up adapter native");
1444             mNativeInterface.cleanup();
1445             mNativeAvailable = false;
1446         }
1447 
1448         if (mAdapterProperties != null) {
1449             mAdapterProperties.cleanup();
1450         }
1451 
1452         if (mNativeInterface.getCallbacks() != null) {
1453             mNativeInterface.getCallbacks().cleanup();
1454         }
1455 
1456         if (mBluetoothKeystoreService != null) {
1457             Log.d(TAG, "cleanup(): mBluetoothKeystoreService.cleanup()");
1458             mBluetoothKeystoreService.cleanup();
1459         }
1460 
1461         mPhonePolicy.ifPresent(policy -> policy.cleanup());
1462 
1463         mSilenceDeviceManager.cleanup();
1464 
1465         if (mActiveDeviceManager != null) {
1466             mActiveDeviceManager.cleanup();
1467         }
1468 
1469         if (mBluetoothSocketManagerBinder != null) {
1470             mBluetoothSocketManagerBinder.cleanUp();
1471             mBluetoothSocketManagerBinder = null;
1472         }
1473 
1474         if (mAdapterSuspend != null) {
1475             if (Flags.adapterSuspendMgmt() && isAtLeastV()) {
1476                 mAdapterSuspend.cleanup();
1477             }
1478             mAdapterSuspend = null;
1479         }
1480 
1481         mPreferredAudioProfilesCallbacks.kill();
1482 
1483         mBluetoothQualityReportReadyCallbacks.kill();
1484 
1485         mBluetoothConnectionCallbacks.kill();
1486 
1487         mSystemServerCallbacks.kill();
1488 
1489         mMetadataListeners.values().forEach(v -> v.kill());
1490     }
1491 
invalidateBluetoothCaches()1492     private static void invalidateBluetoothCaches() {
1493         BluetoothAdapter.invalidateGetProfileConnectionStateCache();
1494         BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache();
1495         BluetoothDevice.invalidateBluetoothGetBondStateCache();
1496         BluetoothAdapter.invalidateGetAdapterConnectionStateCache();
1497         BluetoothMap.invalidateBluetoothGetConnectionStateCache();
1498         BluetoothSap.invalidateBluetoothGetConnectionStateCache();
1499     }
1500 
1501     private static final Map<Integer, Function<AdapterService, ProfileService>>
1502             PROFILE_CONSTRUCTORS =
1503                     Map.ofEntries(
1504                             Map.entry(BluetoothProfile.A2DP, A2dpService::new),
1505                             Map.entry(BluetoothProfile.A2DP_SINK, A2dpSinkService::new),
1506                             Map.entry(BluetoothProfile.AVRCP, AvrcpTargetService::new),
1507                             Map.entry(
1508                                     BluetoothProfile.AVRCP_CONTROLLER, AvrcpControllerService::new),
1509                             Map.entry(
1510                                     BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT,
1511                                     BassClientService::new),
1512                             Map.entry(BluetoothProfile.BATTERY, BatteryService::new),
1513                             Map.entry(
1514                                     BluetoothProfile.CSIP_SET_COORDINATOR,
1515                                     CsipSetCoordinatorService::new),
1516                             Map.entry(BluetoothProfile.HAP_CLIENT, HapClientService::new),
1517                             Map.entry(BluetoothProfile.HEADSET, HeadsetService::new),
1518                             Map.entry(BluetoothProfile.HEADSET_CLIENT, HeadsetClientService::new),
1519                             Map.entry(BluetoothProfile.HEARING_AID, HearingAidService::new),
1520                             Map.entry(BluetoothProfile.HID_DEVICE, HidDeviceService::new),
1521                             Map.entry(BluetoothProfile.HID_HOST, HidHostService::new),
1522                             Map.entry(BluetoothProfile.GATT, GattService::new),
1523                             Map.entry(BluetoothProfile.LE_AUDIO, LeAudioService::new),
1524                             Map.entry(BluetoothProfile.LE_CALL_CONTROL, TbsService::new),
1525                             Map.entry(BluetoothProfile.MAP, BluetoothMapService::new),
1526                             Map.entry(BluetoothProfile.MAP_CLIENT, MapClientService::new),
1527                             Map.entry(BluetoothProfile.MCP_SERVER, McpService::new),
1528                             Map.entry(BluetoothProfile.OPP, BluetoothOppService::new),
1529                             Map.entry(BluetoothProfile.PAN, PanService::new),
1530                             Map.entry(BluetoothProfile.PBAP, BluetoothPbapService::new),
1531                             Map.entry(BluetoothProfile.PBAP_CLIENT, PbapClientService::new),
1532                             Map.entry(BluetoothProfile.SAP, SapService::new),
1533                             Map.entry(BluetoothProfile.VOLUME_CONTROL, VolumeControlService::new));
1534 
1535     @VisibleForTesting
setProfileServiceState(int profileId, int state)1536     void setProfileServiceState(int profileId, int state) {
1537         Instant start = Instant.now();
1538         String logHdr = "setProfileServiceState(" + getProfileName(profileId) + ", " + state + "):";
1539 
1540         if (state == BluetoothAdapter.STATE_ON) {
1541             if (mStartedProfiles.containsKey(profileId)) {
1542                 Log.wtf(TAG, logHdr + " profile is already started");
1543                 return;
1544             }
1545             Log.i(TAG, logHdr + " starting profile");
1546             ProfileService profileService = PROFILE_CONSTRUCTORS.get(profileId).apply(this);
1547             mStartedProfiles.put(profileId, profileService);
1548             addProfile(profileService);
1549             profileService.setAvailable(true);
1550             // With `Flags.onlyStartScanDuringBleOn()` GattService initialization is pushed back to
1551             // `ON` state instead of `BLE_ON`. Here we ensure mGattService is set prior
1552             // to other Profiles using it.
1553             if (profileId == BluetoothProfile.GATT && Flags.onlyStartScanDuringBleOn()) {
1554                 mGattService = GattService.getGattService();
1555             }
1556             onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_ON);
1557         } else if (state == BluetoothAdapter.STATE_OFF) {
1558             ProfileService profileService = mStartedProfiles.remove(profileId);
1559             if (profileService == null) {
1560                 Log.wtf(TAG, logHdr + " profile is already stopped");
1561                 return;
1562             }
1563             Log.i(TAG, logHdr + " stopping profile");
1564             profileService.setAvailable(false);
1565             onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_OFF);
1566             removeProfile(profileService);
1567             profileService.cleanup();
1568             if (profileService.getBinder() != null) {
1569                 profileService.getBinder().cleanup();
1570             }
1571         }
1572         Instant end = Instant.now();
1573         Log.i(TAG, logHdr + " completed in " + Duration.between(start, end).toMillis() + "ms");
1574     }
1575 
setAllProfileServiceStates(int[] profileIds, int state)1576     private void setAllProfileServiceStates(int[] profileIds, int state) {
1577         for (int profileId : profileIds) {
1578             if (!Flags.onlyStartScanDuringBleOn()) {
1579                 // TODO(b/228875190): GATT is assumed supported and treated differently as part of
1580                 //  the "BLE ON" state, despite GATT not being BLE specific.
1581                 if (profileId == BluetoothProfile.GATT) {
1582                     continue;
1583                 }
1584             }
1585             setProfileServiceState(profileId, state);
1586         }
1587     }
1588 
1589     /**
1590      * Checks whether the remote device is a dual mode audio sink device (supports both classic and
1591      * LE Audio sink roles.
1592      *
1593      * @param device the remote device
1594      * @return {@code true} if it's a dual mode audio device, {@code false} otherwise
1595      */
isDualModeAudioSinkDevice(BluetoothDevice device)1596     public boolean isDualModeAudioSinkDevice(BluetoothDevice device) {
1597         if (mLeAudioService == null
1598                 || mLeAudioService.getGroupId(device) == LE_AUDIO_GROUP_ID_INVALID) {
1599             return false;
1600         }
1601 
1602         // Check if any device in the CSIP group is a dual mode audio sink device
1603         for (BluetoothDevice groupDevice :
1604                 mLeAudioService.getGroupDevices(mLeAudioService.getGroupId(device))) {
1605             if (isProfileSupported(groupDevice, BluetoothProfile.LE_AUDIO)
1606                     && (isProfileSupported(groupDevice, BluetoothProfile.HEADSET)
1607                             || isProfileSupported(groupDevice, BluetoothProfile.A2DP))) {
1608                 return true;
1609             }
1610         }
1611         return false;
1612     }
1613 
1614     /**
1615      * Checks whether the local and remote device support a connection for duplex audio (input and
1616      * output) over HFP or LE Audio.
1617      *
1618      * @param groupDevices the devices in the CSIP group
1619      * @return {@code true} if duplex is supported on the remote device, {@code false} otherwise
1620      */
isDuplexAudioSupported(List<BluetoothDevice> groupDevices)1621     private boolean isDuplexAudioSupported(List<BluetoothDevice> groupDevices) {
1622         for (BluetoothDevice device : groupDevices) {
1623             if (isProfileSupported(device, BluetoothProfile.HEADSET)
1624                     || (isProfileSupported(device, BluetoothProfile.LE_AUDIO)
1625                             && mLeAudioService != null
1626                             && mLeAudioService.isLeAudioDuplexSupported(device))) {
1627                 return true;
1628             }
1629         }
1630         return false;
1631     }
1632 
1633     /**
1634      * Checks whether the local and remote device support a connection for output only audio over
1635      * A2DP or LE Audio.
1636      *
1637      * @param groupDevices the devices in the CSIP group
1638      * @return {@code true} if output only is supported, {@code false} otherwise
1639      */
isOutputOnlyAudioSupported(List<BluetoothDevice> groupDevices)1640     private boolean isOutputOnlyAudioSupported(List<BluetoothDevice> groupDevices) {
1641         for (BluetoothDevice device : groupDevices) {
1642             if (isProfileSupported(device, BluetoothProfile.A2DP)
1643                     || (isProfileSupported(device, BluetoothProfile.LE_AUDIO)
1644                             && mLeAudioService != null
1645                             && mLeAudioService.isLeAudioOutputSupported(device))) {
1646                 return true;
1647             }
1648         }
1649         return false;
1650     }
1651 
1652     /**
1653      * Verifies whether the profile is supported by the local bluetooth adapter by checking a
1654      * bitmask of its supported profiles
1655      *
1656      * @param device is the remote device we wish to connect to
1657      * @param profile is the profile we are checking for support
1658      * @return true if the profile is supported by both the local and remote device, false otherwise
1659      */
1660     @VisibleForTesting
isProfileSupported(BluetoothDevice device, int profile)1661     boolean isProfileSupported(BluetoothDevice device, int profile) {
1662         final ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device);
1663         final ParcelUuid[] localDeviceUuids = mAdapterProperties.getUuids();
1664         if (remoteDeviceUuids == null || remoteDeviceUuids.length == 0) {
1665             Log.e(
1666                     TAG,
1667                     "isProfileSupported("
1668                             + ("device=" + device)
1669                             + (", profile=" + BluetoothProfile.getProfileName(profile) + "):")
1670                             + " remote device Uuids Empty");
1671         }
1672 
1673         Log.v(
1674                 TAG,
1675                 "isProfileSupported("
1676                         + ("device=" + device)
1677                         + (", profile=" + BluetoothProfile.getProfileName(profile) + "):")
1678                         + (" local_uuids=" + Arrays.toString(localDeviceUuids))
1679                         + (", remote_uuids=" + Arrays.toString(remoteDeviceUuids)));
1680 
1681         if (profile == BluetoothProfile.HEADSET) {
1682             return (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HSP_AG)
1683                             && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HSP))
1684                     || (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP_AG)
1685                             && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP));
1686         }
1687         if (profile == BluetoothProfile.HEADSET_CLIENT) {
1688             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP_AG)
1689                     && Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP);
1690         }
1691         if (profile == BluetoothProfile.A2DP) {
1692             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST)
1693                     || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SINK);
1694         }
1695         if (profile == BluetoothProfile.A2DP_SINK) {
1696             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST)
1697                     || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SOURCE);
1698         }
1699         if (profile == BluetoothProfile.OPP) {
1700             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.OBEX_OBJECT_PUSH);
1701         }
1702         if (profile == BluetoothProfile.HID_HOST) {
1703             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HID)
1704                     || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HOGP)
1705                     || Utils.arrayContains(
1706                             remoteDeviceUuids, HidHostService.ANDROID_HEADTRACKER_UUID);
1707         }
1708         if (profile == BluetoothProfile.HID_DEVICE) {
1709             return mHidDeviceService.getConnectionState(device) == STATE_DISCONNECTED;
1710         }
1711         if (profile == BluetoothProfile.PAN) {
1712             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.NAP);
1713         }
1714         if (profile == BluetoothProfile.MAP) {
1715             return mMapService.getConnectionState(device) == STATE_CONNECTED;
1716         }
1717         if (profile == BluetoothProfile.PBAP) {
1718             return mPbapService.getConnectionState(device) == STATE_CONNECTED;
1719         }
1720         if (profile == BluetoothProfile.MAP_CLIENT) {
1721             return Utils.arrayContains(localDeviceUuids, BluetoothUuid.MNS)
1722                     && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.MAS);
1723         }
1724         if (profile == BluetoothProfile.PBAP_CLIENT) {
1725             return Utils.arrayContains(localDeviceUuids, BluetoothUuid.PBAP_PCE)
1726                     && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.PBAP_PSE);
1727         }
1728         if (profile == BluetoothProfile.HEARING_AID) {
1729             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HEARING_AID);
1730         }
1731         if (profile == BluetoothProfile.SAP) {
1732             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.SAP);
1733         }
1734         if (profile == BluetoothProfile.VOLUME_CONTROL) {
1735             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.VOLUME_CONTROL);
1736         }
1737         if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) {
1738             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET);
1739         }
1740         if (profile == BluetoothProfile.LE_AUDIO) {
1741             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO);
1742         }
1743         if (profile == BluetoothProfile.HAP_CLIENT) {
1744             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS);
1745         }
1746         if (profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) {
1747             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BASS);
1748         }
1749         if (profile == BluetoothProfile.BATTERY) {
1750             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BATTERY);
1751         }
1752 
1753         Log.e(TAG, "isSupported: Unexpected profile passed in to function: " + profile);
1754         return false;
1755     }
1756 
1757     /**
1758      * Checks if the connection policy of all profiles are unknown for the given device
1759      *
1760      * @param device is the device for which we are checking if the connection policy of all
1761      *     profiles are unknown
1762      * @return false if one of profile is enabled or disabled, true otherwise
1763      */
isAllProfilesUnknown(BluetoothDevice device)1764     boolean isAllProfilesUnknown(BluetoothDevice device) {
1765         if (mHeadsetService != null
1766                 && mHeadsetService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1767             return false;
1768         }
1769         if (mHeadsetClientService != null
1770                 && mHeadsetClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1771             return false;
1772         }
1773         if (mA2dpService != null
1774                 && mA2dpService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1775             return false;
1776         }
1777         if (mA2dpSinkService != null
1778                 && mA2dpSinkService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1779             return false;
1780         }
1781         if (mMapClientService != null
1782                 && mMapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1783             return false;
1784         }
1785         if (mHidHostService != null
1786                 && mHidHostService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1787             return false;
1788         }
1789         if (mPanService != null
1790                 && mPanService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1791             return false;
1792         }
1793         if (mPbapClientService != null
1794                 && mPbapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1795             return false;
1796         }
1797         if (mHearingAidService != null
1798                 && mHearingAidService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1799             return false;
1800         }
1801         if (mHapClientService != null
1802                 && mHapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1803             return false;
1804         }
1805         if (mVolumeControlService != null
1806                 && mVolumeControlService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1807             return false;
1808         }
1809         if (mCsipSetCoordinatorService != null
1810                 && mCsipSetCoordinatorService.getConnectionPolicy(device)
1811                         != CONNECTION_POLICY_UNKNOWN) {
1812             return false;
1813         }
1814         if (mLeAudioService != null
1815                 && mLeAudioService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1816             return false;
1817         }
1818         if (mBassClientService != null
1819                 && mBassClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
1820             return false;
1821         }
1822         return true;
1823     }
1824 
1825     /**
1826      * Connects only available profiles (those with {@link
1827      * BluetoothProfile#CONNECTION_POLICY_ALLOWED})
1828      *
1829      * @param device is the device with which we are connecting the profiles
1830      * @return {@link BluetoothStatusCodes#SUCCESS}
1831      */
connectEnabledProfiles(BluetoothDevice device)1832     private int connectEnabledProfiles(BluetoothDevice device) {
1833         if (mCsipSetCoordinatorService != null
1834                 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR)
1835                 && mCsipSetCoordinatorService.getConnectionPolicy(device)
1836                         > CONNECTION_POLICY_FORBIDDEN) {
1837             Log.i(TAG, "connectEnabledProfiles: Connecting Coordinated Set Profile");
1838             mCsipSetCoordinatorService.connect(device);
1839         }
1840         // Order matters, some devices do not accept A2DP connection before HFP connection
1841         if (mHeadsetService != null
1842                 && isProfileSupported(device, BluetoothProfile.HEADSET)
1843                 && mHeadsetService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1844             Log.i(TAG, "connectEnabledProfiles: Connecting Headset Profile");
1845             mHeadsetService.connect(device);
1846         }
1847         if (mHeadsetClientService != null
1848                 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT)
1849                 && mHeadsetClientService.getConnectionPolicy(device)
1850                         > CONNECTION_POLICY_FORBIDDEN) {
1851             Log.i(TAG, "connectEnabledProfiles: Connecting HFP");
1852             mHeadsetClientService.connect(device);
1853         }
1854         if (mA2dpService != null
1855                 && isProfileSupported(device, BluetoothProfile.A2DP)
1856                 && mA2dpService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1857             Log.i(TAG, "connectEnabledProfiles: Connecting A2dp");
1858             mA2dpService.connect(device);
1859         }
1860         if (mA2dpSinkService != null
1861                 && isProfileSupported(device, BluetoothProfile.A2DP_SINK)
1862                 && mA2dpSinkService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1863             Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink");
1864             mA2dpSinkService.connect(device);
1865         }
1866         if (mMapClientService != null
1867                 && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)
1868                 && mMapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1869             Log.i(TAG, "connectEnabledProfiles: Connecting MAP");
1870             mMapClientService.connect(device);
1871         }
1872         if (mHidHostService != null
1873                 && isProfileSupported(device, BluetoothProfile.HID_HOST)
1874                 && mHidHostService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1875             Log.i(TAG, "connectEnabledProfiles: Connecting Hid Host Profile");
1876             mHidHostService.connect(device);
1877         }
1878         if (mPanService != null
1879                 && isProfileSupported(device, BluetoothProfile.PAN)
1880                 && mPanService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1881             Log.i(TAG, "connectEnabledProfiles: Connecting Pan Profile");
1882             mPanService.connect(device);
1883         }
1884         if (mPbapClientService != null
1885                 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT)
1886                 && mPbapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1887             Log.i(TAG, "connectEnabledProfiles: Connecting Pbap");
1888             mPbapClientService.connect(device);
1889         }
1890         if (mHearingAidService != null
1891                 && isProfileSupported(device, BluetoothProfile.HEARING_AID)
1892                 && mHearingAidService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1893             Log.i(TAG, "connectEnabledProfiles: Connecting Hearing Aid Profile");
1894             mHearingAidService.connect(device);
1895         }
1896         if (mHapClientService != null
1897                 && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)
1898                 && mHapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1899             Log.i(TAG, "connectEnabledProfiles: Connecting HAS Profile");
1900             mHapClientService.connect(device);
1901         }
1902         if (mVolumeControlService != null
1903                 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL)
1904                 && mVolumeControlService.getConnectionPolicy(device)
1905                         > CONNECTION_POLICY_FORBIDDEN) {
1906             Log.i(TAG, "connectEnabledProfiles: Connecting Volume Control Profile");
1907             mVolumeControlService.connect(device);
1908         }
1909         if (mLeAudioService != null
1910                 && isProfileSupported(device, BluetoothProfile.LE_AUDIO)
1911                 && mLeAudioService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1912             Log.i(TAG, "connectEnabledProfiles: Connecting LeAudio profile (BAP)");
1913             mLeAudioService.connect(device);
1914         }
1915         if (mBassClientService != null
1916                 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)
1917                 && mBassClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1918             Log.i(TAG, "connectEnabledProfiles: Connecting LE Broadcast Assistant Profile");
1919             mBassClientService.connect(device);
1920         }
1921         if (mBatteryService != null
1922                 && isProfileSupported(device, BluetoothProfile.BATTERY)
1923                 && mBatteryService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
1924             Log.i(TAG, "connectEnabledProfiles: Connecting Battery Service");
1925             mBatteryService.connect(device);
1926         }
1927         return BluetoothStatusCodes.SUCCESS;
1928     }
1929 
1930     /**
1931      * Verifies that all bluetooth profile services are running
1932      *
1933      * @return true if all bluetooth profile services running, false otherwise
1934      */
profileServicesRunning()1935     private boolean profileServicesRunning() {
1936         if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
1937                 && mRegisteredProfiles.size() == mRunningProfiles.size()) {
1938             return true;
1939         }
1940 
1941         Log.e(TAG, "profileServicesRunning: One or more supported services not running");
1942         return false;
1943     }
1944 
1945     /** Initializes all the profile services fields */
initProfileServices()1946     private void initProfileServices() {
1947         Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services");
1948         mHeadsetService = HeadsetService.getHeadsetService();
1949         mHeadsetClientService = HeadsetClientService.getHeadsetClientService();
1950         mA2dpService = A2dpService.getA2dpService();
1951         mA2dpSinkService = A2dpSinkService.getA2dpSinkService();
1952         mMapService = BluetoothMapService.getBluetoothMapService();
1953         mMapClientService = MapClientService.getMapClientService();
1954         mHidDeviceService = HidDeviceService.getHidDeviceService();
1955         mHidHostService = HidHostService.getHidHostService();
1956         mPanService = PanService.getPanService();
1957         mPbapService = BluetoothPbapService.getBluetoothPbapService();
1958         mPbapClientService = PbapClientService.getPbapClientService();
1959         mHearingAidService = HearingAidService.getHearingAidService();
1960         mHapClientService = HapClientService.getHapClientService();
1961         mSapService = SapService.getSapService();
1962         mVolumeControlService = VolumeControlService.getVolumeControlService();
1963         mCsipSetCoordinatorService = CsipSetCoordinatorService.getCsipSetCoordinatorService();
1964         mLeAudioService = LeAudioService.getLeAudioService();
1965         mBassClientService = BassClientService.getBassClientService();
1966         mBatteryService = BatteryService.getBatteryService();
1967     }
1968 
1969     @BluetoothAdapter.RfcommListenerResult
1970     @RequiresPermission(BLUETOOTH_CONNECT)
startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source)1971     int startRfcommListener(
1972             String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source) {
1973         if (mBluetoothServerSockets.containsKey(uuid.getUuid())) {
1974             Log.d(TAG, "Cannot start RFCOMM listener: UUID " + uuid.getUuid() + "already in use.");
1975             return BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE;
1976         }
1977 
1978         try {
1979             startRfcommListenerInternal(name, uuid.getUuid(), pendingIntent, source);
1980         } catch (IOException e) {
1981             return BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET;
1982         }
1983 
1984         return BluetoothStatusCodes.SUCCESS;
1985     }
1986 
1987     @BluetoothAdapter.RfcommListenerResult
stopRfcommListener(ParcelUuid uuid, AttributionSource source)1988     int stopRfcommListener(ParcelUuid uuid, AttributionSource source) {
1989         RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid());
1990 
1991         if (listenerData == null) {
1992             Log.d(TAG, "Cannot stop RFCOMM listener: UUID " + uuid.getUuid() + "is not registered");
1993             return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD;
1994         }
1995 
1996         if (source.getUid() != listenerData.source.getUid()) {
1997             return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP;
1998         }
1999 
2000         // Remove the entry so that it does not try and restart the server socket.
2001         mBluetoothServerSockets.remove(uuid.getUuid());
2002 
2003         return listenerData.closeServerAndPendingSockets(mHandler);
2004     }
2005 
retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource source)2006     IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord(
2007             ParcelUuid uuid, AttributionSource source) {
2008         IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo();
2009 
2010         RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid());
2011 
2012         if (listenerData == null) {
2013             socketInfo.status =
2014                     BluetoothStatusCodes
2015                             .RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD;
2016             return socketInfo;
2017         }
2018 
2019         if (source.getUid() != listenerData.source.getUid()) {
2020             socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP;
2021             return socketInfo;
2022         }
2023 
2024         BluetoothSocket socket = listenerData.pendingSockets.poll();
2025 
2026         if (socket == null) {
2027             socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE;
2028             return socketInfo;
2029         }
2030 
2031         mHandler.removeCallbacksAndMessages(socket);
2032 
2033         socketInfo.bluetoothDevice = socket.getRemoteDevice();
2034         socketInfo.pfd = socket.getParcelFileDescriptor();
2035         socketInfo.status = BluetoothStatusCodes.SUCCESS;
2036 
2037         return socketInfo;
2038     }
2039 
2040     @RequiresPermission(BLUETOOTH_CONNECT)
handleIncomingRfcommConnections(UUID uuid)2041     private void handleIncomingRfcommConnections(UUID uuid) {
2042         RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid);
2043         while (true) {
2044             BluetoothSocket socket;
2045             try {
2046                 socket = listenerData.serverSocket.accept();
2047             } catch (IOException e) {
2048                 if (mBluetoothServerSockets.containsKey(uuid)) {
2049                     // The uuid still being in the map indicates that the accept failure is
2050                     // unexpected. Try and restart the listener.
2051                     Log.e(TAG, "Failed to accept socket on " + listenerData.serverSocket, e);
2052                     restartRfcommListener(listenerData, uuid);
2053                 }
2054                 return;
2055             }
2056 
2057             listenerData.pendingSockets.add(socket);
2058             try {
2059                 listenerData.pendingIntent.send();
2060             } catch (PendingIntent.CanceledException e) {
2061                 Log.e(TAG, "PendingIntent for RFCOMM socket notifications cancelled.", e);
2062                 // The pending intent was cancelled, close the server as there is no longer any way
2063                 // to notify the app that registered the listener.
2064                 listenerData.closeServerAndPendingSockets(mHandler);
2065                 mBluetoothServerSockets.remove(uuid);
2066                 return;
2067             }
2068             mHandler.postDelayed(
2069                     () -> pendingSocketTimeoutRunnable(listenerData, socket),
2070                     socket,
2071                     PENDING_SOCKET_HANDOFF_TIMEOUT.toMillis());
2072         }
2073     }
2074 
2075     // Tries to restart the rfcomm listener for the given UUID
2076     @RequiresPermission(BLUETOOTH_CONNECT)
restartRfcommListener(RfcommListenerData listenerData, UUID uuid)2077     private void restartRfcommListener(RfcommListenerData listenerData, UUID uuid) {
2078         listenerData.closeServerAndPendingSockets(mHandler);
2079         try {
2080             startRfcommListenerInternal(
2081                     listenerData.name, uuid, listenerData.pendingIntent, listenerData.source);
2082         } catch (IOException e) {
2083             Log.e(TAG, "Failed to recreate rfcomm server socket", e);
2084 
2085             mBluetoothServerSockets.remove(uuid);
2086         }
2087     }
2088 
pendingSocketTimeoutRunnable( RfcommListenerData listenerData, BluetoothSocket socket)2089     private static void pendingSocketTimeoutRunnable(
2090             RfcommListenerData listenerData, BluetoothSocket socket) {
2091         boolean socketFound = listenerData.pendingSockets.remove(socket);
2092         if (socketFound) {
2093             try {
2094                 socket.close();
2095             } catch (IOException e) {
2096                 Log.e(TAG, "Failed to close bt socket", e);
2097                 // We don't care if closing the socket failed, just continue on.
2098             }
2099         }
2100     }
2101 
2102     @RequiresPermission(BLUETOOTH_CONNECT)
startRfcommListenerInternal( String name, UUID uuid, PendingIntent intent, AttributionSource source)2103     private void startRfcommListenerInternal(
2104             String name, UUID uuid, PendingIntent intent, AttributionSource source)
2105             throws IOException {
2106         BluetoothServerSocket bluetoothServerSocket =
2107                 mAdapter.listenUsingRfcommWithServiceRecord(name, uuid);
2108 
2109         RfcommListenerData listenerData =
2110                 new RfcommListenerData(
2111                         bluetoothServerSocket, name, intent, source, new ConcurrentLinkedQueue<>());
2112 
2113         mBluetoothServerSockets.put(uuid, listenerData);
2114 
2115         new Thread(() -> handleIncomingRfcommConnections(uuid)).start();
2116     }
2117 
stopRfcommServerSockets()2118     private void stopRfcommServerSockets() {
2119         Iterator<Map.Entry<UUID, RfcommListenerData>> socketsIterator =
2120                 mBluetoothServerSockets.entrySet().iterator();
2121         while (socketsIterator.hasNext()) {
2122             socketsIterator.next().getValue().closeServerAndPendingSockets(mHandler);
2123             socketsIterator.remove();
2124         }
2125     }
2126 
RfcommListenerData( BluetoothServerSocket serverSocket, String name, PendingIntent pendingIntent, AttributionSource source, ConcurrentLinkedQueue<BluetoothSocket> pendingSockets)2127     private record RfcommListenerData(
2128             BluetoothServerSocket serverSocket,
2129             // Service record name
2130             String name,
2131             // Contains the Service info to which the incoming socket connections are handed off to
2132             PendingIntent pendingIntent,
2133             // AttributionSource for the requester of the RFCOMM listener
2134             AttributionSource source,
2135             // Contains the connected sockets which are pending transfer to the app which requested
2136             // the listener.
2137             ConcurrentLinkedQueue<BluetoothSocket> pendingSockets) {
2138 
2139         int closeServerAndPendingSockets(Handler handler) {
2140             int result = BluetoothStatusCodes.SUCCESS;
2141             try {
2142                 serverSocket.close();
2143             } catch (IOException e) {
2144                 Log.e(TAG, "Failed to call close on rfcomm server socket", e);
2145                 result = BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET;
2146             }
2147             pendingSockets.forEach(
2148                     pendingSocket -> {
2149                         handler.removeCallbacksAndMessages(pendingSocket);
2150                         try {
2151                             pendingSocket.close();
2152                         } catch (IOException e) {
2153                             Log.e(TAG, "Failed to close socket", e);
2154                         }
2155                     });
2156             pendingSockets.clear();
2157             return result;
2158         }
2159     }
2160 
isAvailable()2161     boolean isAvailable() {
2162         return !mCleaningUp;
2163     }
2164 
2165     /**
2166      * Set metadata value for the given device and key
2167      *
2168      * @return true if metadata is set successfully
2169      */
setMetadata(BluetoothDevice device, int key, byte[] value)2170     public boolean setMetadata(BluetoothDevice device, int key, byte[] value) {
2171         if (value == null || value.length > BluetoothDevice.METADATA_MAX_LENGTH) {
2172             return false;
2173         }
2174         return mDatabaseManager.setCustomMeta(device, key, value);
2175     }
2176 
2177     /**
2178      * Get metadata of given device and key
2179      *
2180      * @return value of given device and key combination
2181      */
getMetadata(BluetoothDevice device, int key)2182     public byte[] getMetadata(BluetoothDevice device, int key) {
2183         return mDatabaseManager.getCustomMeta(device, key);
2184     }
2185 
2186     /** Update Adapter Properties when BT profiles connection state changes. */
updateProfileConnectionAdapterProperties( BluetoothDevice device, int profile, int state, int prevState)2187     public void updateProfileConnectionAdapterProperties(
2188             BluetoothDevice device, int profile, int state, int prevState) {
2189         mHandler.post(
2190                 () ->
2191                         mAdapterProperties.updateOnProfileConnectionChanged(
2192                                 device, profile, state, prevState));
2193     }
2194 
2195     /**
2196      * Gets the preferred audio profiles for the device. See {@link
2197      * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)} for more details.
2198      *
2199      * @param device is the remote device whose preferences we want to fetch
2200      * @return a Bundle containing the preferred audio profiles for the device
2201      */
getPreferredAudioProfiles(BluetoothDevice device)2202     public Bundle getPreferredAudioProfiles(BluetoothDevice device) {
2203         if (!isDualModeAudioEnabled()
2204                 || mLeAudioService == null
2205                 || !isDualModeAudioSinkDevice(device)) {
2206             return Bundle.EMPTY;
2207         }
2208         // Checks if the device is part of an LE Audio group
2209         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(device);
2210         if (groupDevices.isEmpty()) {
2211             return Bundle.EMPTY;
2212         }
2213 
2214         // If there are no preferences stored, return the defaults
2215         Bundle storedBundle = Bundle.EMPTY;
2216         for (BluetoothDevice groupDevice : groupDevices) {
2217             Bundle groupDevicePreferences = mDatabaseManager.getPreferredAudioProfiles(groupDevice);
2218             if (!groupDevicePreferences.isEmpty()) {
2219                 storedBundle = groupDevicePreferences;
2220                 break;
2221             }
2222         }
2223 
2224         if (storedBundle.isEmpty()) {
2225             Bundle defaultPreferencesBundle = new Bundle();
2226             boolean useDefaultPreferences = false;
2227             if (isOutputOnlyAudioSupported(groupDevices)) {
2228                 // Gets the default output only audio profile or defaults to LE_AUDIO if not present
2229                 int outputOnlyDefault =
2230                         BluetoothProperties.getDefaultOutputOnlyAudioProfile()
2231                                 .orElse(BluetoothProfile.LE_AUDIO);
2232                 if (outputOnlyDefault != BluetoothProfile.A2DP
2233                         && outputOnlyDefault != BluetoothProfile.LE_AUDIO) {
2234                     outputOnlyDefault = BluetoothProfile.LE_AUDIO;
2235                 }
2236                 defaultPreferencesBundle.putInt(
2237                         BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyDefault);
2238                 useDefaultPreferences = true;
2239             }
2240             if (isDuplexAudioSupported(groupDevices)) {
2241                 // Gets the default duplex audio profile or defaults to LE_AUDIO if not present
2242                 int duplexDefault =
2243                         BluetoothProperties.getDefaultDuplexAudioProfile()
2244                                 .orElse(BluetoothProfile.LE_AUDIO);
2245                 if (duplexDefault != BluetoothProfile.HEADSET
2246                         && duplexDefault != BluetoothProfile.LE_AUDIO) {
2247                     duplexDefault = BluetoothProfile.LE_AUDIO;
2248                 }
2249                 defaultPreferencesBundle.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexDefault);
2250                 useDefaultPreferences = true;
2251             }
2252 
2253             if (useDefaultPreferences) {
2254                 return defaultPreferencesBundle;
2255             }
2256         }
2257         return storedBundle;
2258     }
2259 
2260     /**
2261      * Sets the preferred audio profiles for the device. See {@link
2262      * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)} for more details.
2263      *
2264      * @param device is the remote device whose preferences we want to fetch
2265      * @param modeToProfileBundle is the preferences we want to set for the device
2266      * @return whether the preferences were successfully requested
2267      */
setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle)2268     int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) {
2269         Log.i(TAG, "setPreferredAudioProfiles for device=" + device);
2270         if (!isDualModeAudioEnabled()) {
2271             Log.e(TAG, "setPreferredAudioProfiles called while sysprop is disabled");
2272             return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
2273         }
2274         if (mLeAudioService == null) {
2275             Log.e(TAG, "setPreferredAudioProfiles: LEA service is not up");
2276             return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
2277         }
2278         if (!isDualModeAudioSinkDevice(device)) {
2279             Log.e(TAG, "setPreferredAudioProfiles: Not a dual mode audio device");
2280             return BluetoothStatusCodes.ERROR_NOT_DUAL_MODE_AUDIO_DEVICE;
2281         }
2282         // Checks if the device is part of an LE Audio group
2283         int groupId = mLeAudioService.getGroupId(device);
2284         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId);
2285         if (groupDevices.isEmpty()) {
2286             return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
2287         }
2288 
2289         // Copies relevant keys & values from modeToProfile bundle
2290         Bundle strippedPreferences = new Bundle();
2291         if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)
2292                 && isOutputOnlyAudioSupported(groupDevices)) {
2293             int outputOnlyProfile =
2294                     modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
2295             if (outputOnlyProfile != BluetoothProfile.A2DP
2296                     && outputOnlyProfile != BluetoothProfile.LE_AUDIO) {
2297                 throw new IllegalArgumentException(
2298                         "AUDIO_MODE_OUTPUT_ONLY has invalid value: " + outputOnlyProfile);
2299             }
2300             strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyProfile);
2301         }
2302         if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_DUPLEX)
2303                 && isDuplexAudioSupported(groupDevices)) {
2304             int duplexProfile = modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
2305             if (duplexProfile != BluetoothProfile.HEADSET
2306                     && duplexProfile != BluetoothProfile.LE_AUDIO) {
2307                 throw new IllegalArgumentException(
2308                         "AUDIO_MODE_DUPLEX has invalid value: " + duplexProfile);
2309             }
2310             strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexProfile);
2311         }
2312 
2313         synchronized (mCsipGroupsPendingAudioProfileChanges) {
2314             if (mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) {
2315                 return BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_REQUEST;
2316             }
2317 
2318             Bundle previousPreferences = getPreferredAudioProfiles(device);
2319 
2320             int dbResult =
2321                     mDatabaseManager.setPreferredAudioProfiles(groupDevices, strippedPreferences);
2322             if (dbResult != BluetoothStatusCodes.SUCCESS) {
2323                 return dbResult;
2324             }
2325 
2326             int outputOnlyPreference =
2327                     strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
2328             if (outputOnlyPreference == 0) {
2329                 outputOnlyPreference =
2330                         previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
2331             }
2332             int duplexPreference = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
2333             if (duplexPreference == 0) {
2334                 duplexPreference = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
2335             }
2336 
2337             mLeAudioService.sendAudioProfilePreferencesToNative(
2338                     groupId,
2339                     outputOnlyPreference == BluetoothProfile.LE_AUDIO,
2340                     duplexPreference == BluetoothProfile.LE_AUDIO);
2341 
2342             /* Populates the HashMap to hold requests on the groupId. We will update
2343             numRequestsToAudioFramework after we make requests to the audio framework */
2344             PendingAudioProfilePreferenceRequest holdRequest =
2345                     new PendingAudioProfilePreferenceRequest(strippedPreferences, 0, device);
2346             mCsipGroupsPendingAudioProfileChanges.put(groupId, holdRequest);
2347 
2348             // Notifies audio framework via the handler thread to avoid this blocking calls
2349             mHandler.post(
2350                     () ->
2351                             sendPreferredAudioProfileChangeToAudioFramework(
2352                                     device, strippedPreferences, previousPreferences));
2353             return BluetoothStatusCodes.SUCCESS;
2354         }
2355     }
2356 
2357     /**
2358      * Sends the updated preferred audio profiles to the audio framework.
2359      *
2360      * @param device is the device with updated audio preferences
2361      * @param strippedPreferences is a {@link Bundle} containing the preferences
2362      */
sendPreferredAudioProfileChangeToAudioFramework( BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences)2363     private void sendPreferredAudioProfileChangeToAudioFramework(
2364             BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences) {
2365         int newOutput = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
2366         int newDuplex = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
2367         int previousOutput = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
2368         int previousDuplex = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
2369 
2370         Log.i(
2371                 TAG,
2372                 "sendPreferredAudioProfileChangeToAudioFramework: changing output from "
2373                         + BluetoothProfile.getProfileName(previousOutput)
2374                         + " to "
2375                         + BluetoothProfile.getProfileName(newOutput)
2376                         + " and duplex from "
2377                         + BluetoothProfile.getProfileName(previousDuplex)
2378                         + " to "
2379                         + BluetoothProfile.getProfileName(newDuplex));
2380 
2381         // If no change from existing preferences, do not inform audio framework
2382         if (previousOutput == newOutput && previousDuplex == newDuplex) {
2383             Log.i(TAG, "No change to preferred audio profiles, no requests to Audio FW");
2384             sendPreferredAudioProfilesCallbackToApps(
2385                     device, strippedPreferences, BluetoothStatusCodes.SUCCESS);
2386             return;
2387         }
2388 
2389         int numRequestsToAudioFw = 0;
2390 
2391         // Checks if the device is part of an LE Audio group
2392         int groupId = mLeAudioService.getGroupId(device);
2393         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId);
2394         if (groupDevices.isEmpty()) {
2395             Log.i(
2396                     TAG,
2397                     "sendPreferredAudioProfileChangeToAudioFramework: Empty LEA group for "
2398                             + "device - "
2399                             + device);
2400             sendPreferredAudioProfilesCallbackToApps(
2401                     device, strippedPreferences, BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED);
2402             return;
2403         }
2404 
2405         synchronized (mCsipGroupsPendingAudioProfileChanges) {
2406             if (previousOutput != newOutput) {
2407                 if (newOutput == BluetoothProfile.A2DP
2408                         && mA2dpService.getActiveDevice() != null
2409                         && groupDevices.contains(mA2dpService.getActiveDevice())) {
2410                     Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to A2DP to Audio FW");
2411                     numRequestsToAudioFw +=
2412                             mA2dpService.sendPreferredAudioProfileChangeToAudioFramework();
2413                 } else if (newOutput == BluetoothProfile.LE_AUDIO
2414                         && mLeAudioService.getActiveGroupId() == groupId) {
2415                     Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to LE_AUDIO to Audio FW");
2416                     numRequestsToAudioFw +=
2417                             mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework();
2418                 }
2419             }
2420 
2421             if (previousDuplex != newDuplex) {
2422                 if (newDuplex == BluetoothProfile.HEADSET
2423                         && mHeadsetService.getActiveDevice() != null
2424                         && groupDevices.contains(mHeadsetService.getActiveDevice())) {
2425                     Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to HFP to Audio FW");
2426                     // TODO(b/275426145): Add similar HFP method in BluetoothProfileConnectionInfo
2427                     numRequestsToAudioFw +=
2428                             mA2dpService.sendPreferredAudioProfileChangeToAudioFramework();
2429                 } else if (newDuplex == BluetoothProfile.LE_AUDIO
2430                         && mLeAudioService.getActiveGroupId() == groupId) {
2431                     Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to LE_AUDIO to Audio FW");
2432                     numRequestsToAudioFw +=
2433                             mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework();
2434                 }
2435             }
2436 
2437             Log.i(
2438                     TAG,
2439                     "sendPreferredAudioProfileChangeToAudioFramework: sent "
2440                             + numRequestsToAudioFw
2441                             + " request(s) to the Audio Framework for device: "
2442                             + device);
2443 
2444             if (numRequestsToAudioFw > 0) {
2445                 mCsipGroupsPendingAudioProfileChanges.put(
2446                         groupId,
2447                         new PendingAudioProfilePreferenceRequest(
2448                                 strippedPreferences, numRequestsToAudioFw, device));
2449 
2450                 Message m =
2451                         mHandler.obtainMessage(
2452                                 MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT);
2453                 m.obj = groupId;
2454                 mHandler.sendMessageDelayed(m, PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT.toMillis());
2455                 return;
2456             }
2457         }
2458         sendPreferredAudioProfilesCallbackToApps(
2459                 device, strippedPreferences, BluetoothStatusCodes.SUCCESS);
2460     }
2461 
removeFromPendingAudioProfileChanges(int groupId)2462     private void removeFromPendingAudioProfileChanges(int groupId) {
2463         synchronized (mCsipGroupsPendingAudioProfileChanges) {
2464             Log.i(
2465                     TAG,
2466                     "removeFromPendingAudioProfileChanges: Timeout on change for groupId="
2467                             + groupId);
2468             if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) {
2469                 Log.e(
2470                         TAG,
2471                         "removeFromPendingAudioProfileChanges( "
2472                                 + groupId
2473                                 + ", "
2474                                 + groupId
2475                                 + ") is not pending");
2476                 return;
2477             }
2478         }
2479     }
2480 
2481     /**
2482      * Notification from the audio framework that an active device change has taken effect. See
2483      * {@link BluetoothAdapter#notifyActiveDeviceChangeApplied(BluetoothDevice)} for more details.
2484      *
2485      * @param device the remote device whose preferred audio profiles have been changed
2486      * @return whether the Bluetooth stack acknowledged the change successfully
2487      */
notifyActiveDeviceChangeApplied(BluetoothDevice device)2488     int notifyActiveDeviceChangeApplied(BluetoothDevice device) {
2489         if (mLeAudioService == null) {
2490             Log.e(TAG, "LE Audio profile not enabled");
2491             return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
2492         }
2493 
2494         int groupId = mLeAudioService.getGroupId(device);
2495         if (groupId == LE_AUDIO_GROUP_ID_INVALID) {
2496             return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
2497         }
2498 
2499         synchronized (mCsipGroupsPendingAudioProfileChanges) {
2500             if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) {
2501                 Log.e(
2502                         TAG,
2503                         "notifyActiveDeviceChangeApplied, but no pending request for "
2504                                 + "groupId: "
2505                                 + groupId);
2506                 return BluetoothStatusCodes.ERROR_UNKNOWN;
2507             }
2508 
2509             PendingAudioProfilePreferenceRequest pendingRequest =
2510                     mCsipGroupsPendingAudioProfileChanges.get(groupId);
2511 
2512             // If this is the final audio framework request, send callback to apps
2513             if (pendingRequest.numberOfRemainingRequestsToAudioFramework == 1) {
2514                 Log.i(
2515                         TAG,
2516                         "notifyActiveDeviceChangeApplied: Complete for device "
2517                                 + pendingRequest.device);
2518                 sendPreferredAudioProfilesCallbackToApps(
2519                         pendingRequest.device,
2520                         pendingRequest.preferences,
2521                         BluetoothStatusCodes.SUCCESS);
2522                 // Removes the timeout from the handler
2523                 mHandler.removeMessages(
2524                         MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT, groupId);
2525             } else if (pendingRequest.numberOfRemainingRequestsToAudioFramework > 1) {
2526                 PendingAudioProfilePreferenceRequest updatedPendingRequest =
2527                         new PendingAudioProfilePreferenceRequest(
2528                                 pendingRequest.preferences,
2529                                 pendingRequest.numberOfRemainingRequestsToAudioFramework - 1,
2530                                 pendingRequest.device);
2531                 Log.i(
2532                         TAG,
2533                         "notifyActiveDeviceChangeApplied: Updating device "
2534                                 + updatedPendingRequest.device
2535                                 + " with new remaining requests count="
2536                                 + updatedPendingRequest.numberOfRemainingRequestsToAudioFramework);
2537                 mCsipGroupsPendingAudioProfileChanges.put(groupId, updatedPendingRequest);
2538             } else {
2539                 Log.i(
2540                         TAG,
2541                         "notifyActiveDeviceChangeApplied: "
2542                                 + pendingRequest.device
2543                                 + " has no remaining requests to audio framework, but is still"
2544                                 + " present in mCsipGroupsPendingAudioProfileChanges");
2545             }
2546         }
2547 
2548         return BluetoothStatusCodes.SUCCESS;
2549     }
2550 
sendPreferredAudioProfilesCallbackToApps( BluetoothDevice device, Bundle preferredAudioProfiles, int status)2551     private void sendPreferredAudioProfilesCallbackToApps(
2552             BluetoothDevice device, Bundle preferredAudioProfiles, int status) {
2553         int n = mPreferredAudioProfilesCallbacks.beginBroadcast();
2554         Log.d(
2555                 TAG,
2556                 "sendPreferredAudioProfilesCallbackToApps() - Broadcasting audio profile "
2557                         + ("change callback to device: " + device)
2558                         + (" and status=" + status)
2559                         + (" to " + n + " receivers."));
2560         for (int i = 0; i < n; i++) {
2561             try {
2562                 mPreferredAudioProfilesCallbacks
2563                         .getBroadcastItem(i)
2564                         .onPreferredAudioProfilesChanged(device, preferredAudioProfiles, status);
2565             } catch (RemoteException e) {
2566                 Log.d(
2567                         TAG,
2568                         "sendPreferredAudioProfilesCallbackToApps() - Callback #"
2569                                 + i
2570                                 + " failed ("
2571                                 + e
2572                                 + ")");
2573             }
2574         }
2575         mPreferredAudioProfilesCallbacks.finishBroadcast();
2576     }
2577 
2578     // ----API Methods--------
2579 
isEnabled()2580     public boolean isEnabled() {
2581         return getState() == BluetoothAdapter.STATE_ON;
2582     }
2583 
getState()2584     public int getState() {
2585         if (mAdapterProperties != null) {
2586             return mAdapterProperties.getState();
2587         }
2588         return BluetoothAdapter.STATE_OFF;
2589     }
2590 
offToBleOn(boolean quietMode)2591     public synchronized void offToBleOn(boolean quietMode) {
2592         // Enforce the user restriction for disallowing Bluetooth if it was set.
2593         if (mUserManager.hasUserRestrictionForUser(
2594                 UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
2595             Log.d(TAG, "offToBleOn() called when Bluetooth was disallowed");
2596             return;
2597         }
2598         // The call to init must be done on the main thread
2599         mHandler.post(() -> init());
2600 
2601         Log.i(TAG, "offToBleOn() - Enable called with quiet mode status =  " + quietMode);
2602         mQuietmode = quietMode;
2603         mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
2604     }
2605 
onToBleOn()2606     void onToBleOn() {
2607         Log.d(TAG, "onToBleOn() called with mRunningProfiles.size() = " + mRunningProfiles.size());
2608         mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF);
2609     }
2610 
disconnectAllAcls()2611     void disconnectAllAcls() {
2612         Log.d(TAG, "disconnectAllAcls()");
2613         mNativeInterface.disconnectAllAcls();
2614     }
2615 
getName()2616     public String getName() {
2617         return mAdapterProperties.getName();
2618     }
2619 
getNameLengthForAdvertise()2620     public int getNameLengthForAdvertise() {
2621         return mAdapterProperties.getName().length();
2622     }
2623 
getDiscoveringPackages()2624     List<DiscoveringPackage> getDiscoveringPackages() {
2625         return mDiscoveringPackages;
2626     }
2627 
clearDiscoveringPackages()2628     void clearDiscoveringPackages() {
2629         synchronized (mDiscoveringPackages) {
2630             mDiscoveringPackages.clear();
2631         }
2632     }
2633 
startDiscovery(AttributionSource source)2634     boolean startDiscovery(AttributionSource source) {
2635         UserHandle callingUser = Binder.getCallingUserHandle();
2636         Log.d(TAG, "startDiscovery");
2637         String callingPackage = source.getPackageName();
2638         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
2639         boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q);
2640         boolean hasDisavowedLocation =
2641                 Utils.hasDisavowedLocationForScan(this, source, mTestModeEnabled);
2642         String permission = null;
2643         if (Utils.checkCallerHasNetworkSettingsPermission(this)) {
2644             permission = android.Manifest.permission.NETWORK_SETTINGS;
2645         } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) {
2646             permission = android.Manifest.permission.NETWORK_SETUP_WIZARD;
2647         } else if (!hasDisavowedLocation) {
2648             if (isQApp) {
2649                 if (!Utils.checkCallerHasFineLocation(this, source, callingUser)) {
2650                     return false;
2651                 }
2652                 permission = android.Manifest.permission.ACCESS_FINE_LOCATION;
2653             } else {
2654                 if (!Utils.checkCallerHasCoarseLocation(this, source, callingUser)) {
2655                     return false;
2656                 }
2657                 permission = android.Manifest.permission.ACCESS_COARSE_LOCATION;
2658             }
2659         }
2660 
2661         synchronized (mDiscoveringPackages) {
2662             mDiscoveringPackages.add(
2663                     new DiscoveringPackage(callingPackage, permission, hasDisavowedLocation));
2664         }
2665         return mNativeInterface.startDiscovery();
2666     }
2667 
2668     /**
2669      * Same as API method {@link BluetoothAdapter#getBondedDevices()}
2670      *
2671      * @return array of bonded {@link BluetoothDevice} or null on error
2672      */
getBondedDevices()2673     public BluetoothDevice[] getBondedDevices() {
2674         return mAdapterProperties.getBondedDevices();
2675     }
2676 
2677     /**
2678      * Get the database manager to access Bluetooth storage
2679      *
2680      * @return {@link DatabaseManager} or null on error
2681      */
getDatabase()2682     public DatabaseManager getDatabase() {
2683         return mDatabaseManager;
2684     }
2685 
getByteIdentityAddress(BluetoothDevice device)2686     public byte[] getByteIdentityAddress(BluetoothDevice device) {
2687         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
2688         if (deviceProp != null && deviceProp.getIdentityAddress() != null) {
2689             return Utils.getBytesFromAddress(deviceProp.getIdentityAddress());
2690         }
2691 
2692         // Return null if identity address unknown
2693         return null;
2694     }
2695 
getDeviceFromByte(byte[] address)2696     public BluetoothDevice getDeviceFromByte(byte[] address) {
2697         BluetoothDevice device = mRemoteDevices.getDevice(address);
2698         if (device == null) {
2699             device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
2700         }
2701         return device;
2702     }
2703 
getIdentityAddress(String address)2704     public String getIdentityAddress(String address) {
2705         BluetoothDevice device =
2706                 BluetoothAdapter.getDefaultAdapter()
2707                         .getRemoteDevice(address.toUpperCase(Locale.ROOT));
2708         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
2709         if (deviceProp != null && deviceProp.getIdentityAddress() != null) {
2710             return deviceProp.getIdentityAddress();
2711         }
2712         // Return null if identity address unknown
2713         return null;
2714     }
2715 
2716     /**
2717      * Returns the identity address and identity address type.
2718      *
2719      * @param address of remote device
2720      * @return a {@link BluetoothDevice.BluetoothAddress} containing identity address and identity
2721      *     address type
2722      */
2723     @NonNull
getIdentityAddressWithType(@onNull String address)2724     public BluetoothAddress getIdentityAddressWithType(@NonNull String address) {
2725         BluetoothDevice device =
2726                 BluetoothAdapter.getDefaultAdapter()
2727                         .getRemoteDevice(address.toUpperCase(Locale.ROOT));
2728         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
2729 
2730         String identityAddress = null;
2731         int identityAddressType = BluetoothDevice.ADDRESS_TYPE_UNKNOWN;
2732 
2733         if (deviceProp != null) {
2734             if (deviceProp.getIdentityAddress() != null) {
2735                 identityAddress = deviceProp.getIdentityAddress();
2736             }
2737             identityAddressType = deviceProp.getIdentityAddressType();
2738         } else {
2739             identityAddress = null;
2740         }
2741 
2742         return new BluetoothAddress(identityAddress, identityAddressType);
2743     }
2744 
addAssociatedPackage(BluetoothDevice device, String packageName)2745     public boolean addAssociatedPackage(BluetoothDevice device, String packageName) {
2746         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
2747         if (deviceProp == null) {
2748             return false;
2749         }
2750         deviceProp.addPackage(packageName);
2751         return true;
2752     }
2753 
CallerInfo(String callerPackageName, UserHandle user)2754     private record CallerInfo(String callerPackageName, UserHandle user) {}
2755 
createBond( BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, String callingPackage)2756     boolean createBond(
2757             BluetoothDevice device,
2758             int transport,
2759             OobData remoteP192Data,
2760             OobData remoteP256Data,
2761             String callingPackage) {
2762         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
2763         if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
2764             // true for BONDING, false for BONDED
2765             return deviceProp.getBondState() == BluetoothDevice.BOND_BONDING;
2766         }
2767 
2768         if (!isEnabled()) {
2769             Log.e(TAG, "Impossible to call createBond when Bluetooth is not enabled");
2770             return false;
2771         }
2772 
2773         if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) {
2774             return false;
2775         }
2776 
2777         CallerInfo createBondCaller = new CallerInfo(callingPackage, Binder.getCallingUserHandle());
2778         mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller);
2779 
2780         mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
2781 
2782         // Pairing is unreliable while scanning, so cancel discovery
2783         // Note, remove this when native stack improves
2784         mNativeInterface.cancelDiscovery();
2785 
2786         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
2787         msg.obj = device;
2788         msg.arg1 = transport;
2789 
2790         Bundle remoteOobDatasBundle = new Bundle();
2791         boolean setData = false;
2792         if (remoteP192Data != null) {
2793             remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data);
2794             setData = true;
2795         }
2796         if (remoteP256Data != null) {
2797             remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data);
2798             setData = true;
2799         }
2800         if (setData) {
2801             msg.setData(remoteOobDatasBundle);
2802         } else {
2803             MetricsLogger.getInstance()
2804                     .logBluetoothEvent(
2805                             device,
2806                             BluetoothStatsLog
2807                                     .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__BONDING,
2808                             BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START,
2809                             Binder.getCallingUid());
2810         }
2811         mBondStateMachine.sendMessage(msg);
2812         return true;
2813     }
2814 
2815     /**
2816      * Fetches the local OOB data to give out to remote.
2817      *
2818      * @param transport - specify data transport.
2819      * @param callback - callback used to receive the requested {@link OobData}; null will be
2820      *     ignored silently.
2821      */
generateLocalOobData( int transport, IBluetoothOobDataCallback callback)2822     public synchronized void generateLocalOobData(
2823             int transport, IBluetoothOobDataCallback callback) {
2824         if (callback == null) {
2825             Log.e(TAG, "'callback' argument must not be null!");
2826             return;
2827         }
2828         if (mOobDataCallbackQueue.peek() != null) {
2829             try {
2830                 callback.onError(BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST);
2831             } catch (RemoteException e) {
2832                 Log.e(TAG, "Failed to make callback", e);
2833             }
2834             return;
2835         }
2836         mOobDataCallbackQueue.offer(callback);
2837         mHandler.postDelayed(
2838                 () -> removeFromOobDataCallbackQueue(callback),
2839                 GENERATE_LOCAL_OOB_DATA_TIMEOUT.toMillis());
2840         mNativeInterface.generateLocalOobData(transport);
2841     }
2842 
removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback)2843     private synchronized void removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback) {
2844         if (callback == null) {
2845             return;
2846         }
2847 
2848         if (mOobDataCallbackQueue.peek() == callback) {
2849             try {
2850                 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN);
2851             } catch (RemoteException e) {
2852                 Log.e(TAG, "Failed to make OobDataCallback to remove callback from queue", e);
2853             }
2854         }
2855     }
2856 
notifyOobDataCallback(int transport, OobData oobData)2857     /* package */ synchronized void notifyOobDataCallback(int transport, OobData oobData) {
2858         if (mOobDataCallbackQueue.peek() == null) {
2859             Log.e(TAG, "Failed to make callback, no callback exists");
2860             return;
2861         }
2862         if (oobData == null) {
2863             try {
2864                 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN);
2865             } catch (RemoteException e) {
2866                 Log.e(TAG, "Failed to make callback", e);
2867             }
2868         } else {
2869             try {
2870                 mOobDataCallbackQueue.poll().onOobData(transport, oobData);
2871             } catch (RemoteException e) {
2872                 Log.e(TAG, "Failed to make callback", e);
2873             }
2874         }
2875     }
2876 
isQuietModeEnabled()2877     public boolean isQuietModeEnabled() {
2878         Log.d(TAG, "isQuietModeEnabled() - Enabled = " + mQuietmode);
2879         return mQuietmode;
2880     }
2881 
updateUuids()2882     public void updateUuids() {
2883         Log.d(TAG, "updateUuids() - Updating UUIDs for bonded devices");
2884         BluetoothDevice[] bondedDevices = getBondedDevices();
2885         if (bondedDevices == null) {
2886             return;
2887         }
2888 
2889         for (BluetoothDevice device : bondedDevices) {
2890             mRemoteDevices.updateUuids(device);
2891         }
2892     }
2893 
2894     /**
2895      * Update device UUID changed to {@link BondStateMachine}
2896      *
2897      * @param device remote device of interest
2898      */
deviceUuidUpdated(BluetoothDevice device)2899     public void deviceUuidUpdated(BluetoothDevice device) {
2900         // Notify BondStateMachine for SDP complete / UUID changed.
2901         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE);
2902         msg.obj = device;
2903         mBondStateMachine.sendMessage(msg);
2904     }
2905 
2906     /**
2907      * Get the bond state of a particular {@link BluetoothDevice}
2908      *
2909      * @param device remote device of interest
2910      * @return bond state
2911      *     <p>Possible values are {@link BluetoothDevice#BOND_NONE}, {@link
2912      *     BluetoothDevice#BOND_BONDING}, {@link BluetoothDevice#BOND_BONDED}.
2913      */
getBondState(BluetoothDevice device)2914     public int getBondState(BluetoothDevice device) {
2915         return mRemoteDevices.getBondState(device);
2916     }
2917 
isConnected(BluetoothDevice device)2918     public boolean isConnected(BluetoothDevice device) {
2919         return getConnectionState(device) != BluetoothDevice.CONNECTION_STATE_DISCONNECTED;
2920     }
2921 
addGattClientToControlAutoActiveMode(int clientIf, BluetoothDevice device)2922     private void addGattClientToControlAutoActiveMode(int clientIf, BluetoothDevice device) {
2923         if (!Flags.allowGattConnectFromTheAppsWithoutMakingLeaudioDeviceActive()) {
2924             Log.i(
2925                     TAG,
2926                     "flag: allowGattConnectFromTheAppsWithoutMakingLeaudioDeviceActive is not"
2927                             + " enabled");
2928             return;
2929         }
2930 
2931         /* When GATT client is connecting to LeAudio device, stack should not assume that
2932          * LeAudio device should be automatically connected to Audio Framework.
2933          * e.g. given LeAudio device might be busy with audio streaming from another device.
2934          * LeAudio shall be automatically connected to Audio Framework when
2935          * 1. Remote device expects that - Targeted Announcements are used
2936          * 2. User is connecting device from Settings application.
2937          *
2938          * Above conditions are tracked by LeAudioService. In here, there is need to notify
2939          * LeAudioService that connection is made for GATT purposes, so LeAudioService can
2940          * disable AutoActiveMode and make sure to not make device Active just after connection
2941          * is created.
2942          *
2943          * Note: AutoActiveMode is by default set to true and it means that LeAudio device is ready
2944          * to streaming just after connection is created. That implies that device will be connected
2945          * to Audio Framework (is made Active) when connection is created.
2946          */
2947 
2948         int groupId = mLeAudioService.getGroupId(device);
2949         if (groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
2950             /* If this is not a LeAudio device, there is nothing to do here. */
2951             return;
2952         }
2953 
2954         if (mLeAudioService.getConnectionPolicy(device) != CONNECTION_POLICY_ALLOWED) {
2955             Log.d(
2956                     TAG,
2957                     "addGattClientToControlAutoActiveMode: "
2958                             + device
2959                             + " LeAudio connection policy is not allowed");
2960             return;
2961         }
2962 
2963         Log.i(
2964                 TAG,
2965                 "addGattClientToControlAutoActiveMode: clientIf: "
2966                         + clientIf
2967                         + ", "
2968                         + device
2969                         + ", groupId: "
2970                         + groupId);
2971 
2972         synchronized (mLeGattClientsControllingAutoActiveMode) {
2973             Pair newPair = new Pair<>(clientIf, device);
2974             if (mLeGattClientsControllingAutoActiveMode.contains(newPair)) {
2975                 return;
2976             }
2977 
2978             for (Pair<Integer, BluetoothDevice> pair : mLeGattClientsControllingAutoActiveMode) {
2979                 if (pair.second.equals(device)
2980                         || groupId == mLeAudioService.getGroupId(pair.second)) {
2981                     Log.i(TAG, "addGattClientToControlAutoActiveMode: adding new client");
2982                     mLeGattClientsControllingAutoActiveMode.add(newPair);
2983                     return;
2984                 }
2985             }
2986 
2987             if (mLeAudioService.setAutoActiveModeState(mLeAudioService.getGroupId(device), false)) {
2988                 Log.i(
2989                         TAG,
2990                         "addGattClientToControlAutoActiveMode: adding new client and notifying"
2991                                 + " leAudioService");
2992                 mLeGattClientsControllingAutoActiveMode.add(newPair);
2993             }
2994         }
2995     }
2996 
2997     /**
2998      * When this is called, AdapterService is aware of user doing GATT connection over LE. Adapter
2999      * service will use this information to manage internal GATT services if needed. For now,
3000      * AdapterService is using this information to control Auto Active Mode for LeAudio devices.
3001      *
3002      * @param clientIf clientIf ClientIf which was doing GATT connection attempt
3003      * @param device device Remote device to connect
3004      */
notifyDirectLeGattClientConnect(int clientIf, BluetoothDevice device)3005     public void notifyDirectLeGattClientConnect(int clientIf, BluetoothDevice device) {
3006         if (mLeAudioService != null) {
3007             addGattClientToControlAutoActiveMode(clientIf, device);
3008         }
3009     }
3010 
removeGattClientFromControlAutoActiveMode(int clientIf, BluetoothDevice device)3011     private void removeGattClientFromControlAutoActiveMode(int clientIf, BluetoothDevice device) {
3012         if (mLeGattClientsControllingAutoActiveMode.isEmpty()) {
3013             return;
3014         }
3015 
3016         int groupId = mLeAudioService.getGroupId(device);
3017         if (groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
3018             /* If this is not a LeAudio device, there is nothing to do here. */
3019             return;
3020         }
3021 
3022         /* Remember if auto active mode is still disabled.
3023          * If it is disabled, it means, that either User or remote device did not make an
3024          * action to make LeAudio device Active.
3025          * That means, AdapterService should disconnect ACL when all the clients are disconnected
3026          * from the group to which the device belongs.
3027          */
3028         boolean isAutoActiveModeDisabled = !mLeAudioService.isAutoActiveModeEnabled(groupId);
3029 
3030         synchronized (mLeGattClientsControllingAutoActiveMode) {
3031             Log.d(
3032                     TAG,
3033                     "removeGattClientFromControlAutoActiveMode: removing clientIf:"
3034                             + clientIf
3035                             + ", "
3036                             + device
3037                             + ", groupId: "
3038                             + groupId);
3039 
3040             mLeGattClientsControllingAutoActiveMode.remove(new Pair<>(clientIf, device));
3041 
3042             if (!mLeGattClientsControllingAutoActiveMode.isEmpty()) {
3043                 for (Pair<Integer, BluetoothDevice> pair :
3044                         mLeGattClientsControllingAutoActiveMode) {
3045                     if (pair.second.equals(device)
3046                             || groupId == mLeAudioService.getGroupId(pair.second)) {
3047                         Log.d(
3048                                 TAG,
3049                                 "removeGattClientFromControlAutoActiveMode:"
3050                                         + device
3051                                         + " or groupId: "
3052                                         + groupId
3053                                         + " is still in use by clientif: "
3054                                         + pair.first);
3055                         return;
3056                     }
3057                 }
3058             }
3059 
3060             /* Back auto active mode to default. */
3061             mLeAudioService.setAutoActiveModeState(groupId, true);
3062         }
3063 
3064         int leConnectedState =
3065                 BluetoothDevice.CONNECTION_STATE_ENCRYPTED_LE
3066                         | BluetoothDevice.CONNECTION_STATE_CONNECTED;
3067 
3068         /* If auto active mode was disabled for the given group and is still connected
3069          * make sure to disconnected all the devices from the group
3070          */
3071         if (isAutoActiveModeDisabled && ((getConnectionState(device) & leConnectedState) != 0)) {
3072             for (BluetoothDevice dev : mLeAudioService.getGroupDevices(groupId)) {
3073                 /* Need to disconnect all the devices from the group as those might be connected
3074                  * as well especially those which might keep the connection
3075                  */
3076                 if ((getConnectionState(dev) & leConnectedState) != 0) {
3077                     mNativeInterface.disconnectAcl(dev, BluetoothDevice.TRANSPORT_LE);
3078                 }
3079             }
3080         }
3081     }
3082 
3083     /**
3084      * Notify AdapterService about failed GATT connection attempt.
3085      *
3086      * @param clientIf ClientIf which was doing GATT connection attempt
3087      * @param device Remote device to which connection attempt failed
3088      */
notifyGattClientConnectFailed(int clientIf, BluetoothDevice device)3089     public void notifyGattClientConnectFailed(int clientIf, BluetoothDevice device) {
3090         if (mLeAudioService != null) {
3091             removeGattClientFromControlAutoActiveMode(clientIf, device);
3092         }
3093     }
3094 
3095     /**
3096      * Notify AdapterService about GATT connection being disconnecting or disconnected.
3097      *
3098      * @param clientIf ClientIf which is disconnecting or is already disconnected
3099      * @param device Remote device which is disconnecting or is disconnected
3100      */
notifyGattClientDisconnect(int clientIf, BluetoothDevice device)3101     public void notifyGattClientDisconnect(int clientIf, BluetoothDevice device) {
3102         if (mLeAudioService != null) {
3103             removeGattClientFromControlAutoActiveMode(clientIf, device);
3104         }
3105     }
3106 
getConnectionState(BluetoothDevice device)3107     public int getConnectionState(BluetoothDevice device) {
3108         final String address = device.getAddress();
3109         int connectionState = mNativeInterface.getConnectionState(getBytesFromAddress(address));
3110         final String identityAddress = getIdentityAddress(address);
3111         if (identityAddress != null) {
3112             connectionState |=
3113                     mNativeInterface.getConnectionState(getBytesFromAddress(identityAddress));
3114         }
3115         return connectionState;
3116     }
3117 
getConnectionHandle(BluetoothDevice device, int transport)3118     int getConnectionHandle(BluetoothDevice device, int transport) {
3119         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
3120         if (deviceProp == null) {
3121             return BluetoothDevice.ERROR;
3122         }
3123         return deviceProp.getConnectionHandle(transport);
3124     }
3125 
3126     /**
3127      * Get ASHA Capability
3128      *
3129      * @param device discovered bluetooth device
3130      * @return ASHA capability
3131      */
getAshaCapability(BluetoothDevice device)3132     public int getAshaCapability(BluetoothDevice device) {
3133         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
3134         if (deviceProp == null) {
3135             return BluetoothDevice.ERROR;
3136         }
3137         return deviceProp.getAshaCapability();
3138     }
3139 
3140     /**
3141      * Get ASHA truncated HiSyncId
3142      *
3143      * @param device discovered bluetooth device
3144      * @return ASHA truncated HiSyncId
3145      */
getAshaTruncatedHiSyncId(BluetoothDevice device)3146     public int getAshaTruncatedHiSyncId(BluetoothDevice device) {
3147         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
3148         if (deviceProp == null) {
3149             return BluetoothDevice.ERROR;
3150         }
3151         return deviceProp.getAshaTruncatedHiSyncId();
3152     }
3153 
3154     /**
3155      * Checks whether the device was recently associated with the companion app that called {@link
3156      * BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if their
3157      * pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}.
3158      *
3159      * @param device the bluetooth device that is being bonded
3160      * @return true if it was recently associated and we can bypass the dialog, false otherwise
3161      */
canBondWithoutDialog(BluetoothDevice device)3162     public boolean canBondWithoutDialog(BluetoothDevice device) {
3163         if (mBondAttemptCallerInfo.containsKey(device.getAddress())) {
3164             CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress());
3165 
3166             return mCompanionDeviceManager.canPairWithoutPrompt(
3167                     bondCallerInfo.callerPackageName, device.getAddress(), bondCallerInfo.user);
3168         }
3169         return false;
3170     }
3171 
3172     /**
3173      * Returns the package name of the most recent caller that called {@link
3174      * BluetoothDevice#createBond} on the given device.
3175      */
3176     @Nullable
getPackageNameOfBondingApplication(BluetoothDevice device)3177     public String getPackageNameOfBondingApplication(BluetoothDevice device) {
3178         CallerInfo info = mBondAttemptCallerInfo.get(device.getAddress());
3179         if (info == null) {
3180             return null;
3181         }
3182         return info.callerPackageName;
3183     }
3184 
3185     /**
3186      * Sets device as the active devices for the profiles passed into the function.
3187      *
3188      * @param device is the remote bluetooth device
3189      * @param profiles is a constant that references for which profiles we'll be setting the remote
3190      *     device as our active device. One of the following: {@link
3191      *     BluetoothAdapter#ACTIVE_DEVICE_AUDIO}, {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL}
3192      *     {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
3193      * @return false if profiles value is not one of the constants we accept, true otherwise
3194      */
setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles)3195     public boolean setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles) {
3196         if (getState() != BluetoothAdapter.STATE_ON) {
3197             Log.e(TAG, "setActiveDevice: Bluetooth is not enabled");
3198             return false;
3199         }
3200         boolean setHeadset = false;
3201         boolean setA2dp = false;
3202 
3203         // Determine for which profiles we want to set device as our active device
3204         switch (profiles) {
3205             case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL -> setHeadset = true;
3206             case BluetoothAdapter.ACTIVE_DEVICE_AUDIO -> setA2dp = true;
3207             case BluetoothAdapter.ACTIVE_DEVICE_ALL -> {
3208                 setHeadset = true;
3209                 setA2dp = true;
3210             }
3211             default -> {
3212                 return false;
3213             }
3214         }
3215 
3216         boolean hfpSupported =
3217                 mHeadsetService != null
3218                         && (device == null
3219                                 || mHeadsetService.getConnectionPolicy(device)
3220                                         == CONNECTION_POLICY_ALLOWED);
3221         boolean a2dpSupported =
3222                 mA2dpService != null
3223                         && (device == null
3224                                 || mA2dpService.getConnectionPolicy(device)
3225                                         == CONNECTION_POLICY_ALLOWED);
3226         boolean leAudioSupported =
3227                 mLeAudioService != null
3228                         && (device == null
3229                                 || mLeAudioService.getConnectionPolicy(device)
3230                                         == CONNECTION_POLICY_ALLOWED);
3231 
3232         if (leAudioSupported) {
3233             Log.i(TAG, "setActiveDevice: Setting active Le Audio device " + device);
3234             if (device == null) {
3235                 /* If called by BluetoothAdapter it means Audio should not be stopped.
3236                  * For this reason let's say that fallback device exists
3237                  */
3238                 mLeAudioService.removeActiveDevice(true /* hasFallbackDevice */);
3239             } else {
3240                 if (mA2dpService != null && mA2dpService.getActiveDevice() != null) {
3241                     // TODO:  b/312396770
3242                     mA2dpService.removeActiveDevice(false);
3243                 }
3244                 mLeAudioService.setActiveDevice(device);
3245             }
3246         }
3247 
3248         // Order matters, some devices do not accept A2DP connection before HFP connection
3249         if (setHeadset && hfpSupported) {
3250             Log.i(TAG, "setActiveDevice: Setting active Headset " + device);
3251             mHeadsetService.setActiveDevice(device);
3252         }
3253 
3254         if (setA2dp && a2dpSupported) {
3255             Log.i(TAG, "setActiveDevice: Setting active A2dp device " + device);
3256             if (device == null) {
3257                 mA2dpService.removeActiveDevice(false);
3258             } else {
3259                 /* Workaround for the controller issue which is not able to handle correctly
3260                  * A2DP offloader vendor specific command while ISO Data path is set.
3261                  * Proper solutions should be delivered in b/312396770
3262                  */
3263                 if (mLeAudioService != null) {
3264                     List<BluetoothDevice> activeLeAudioDevices = mLeAudioService.getActiveDevices();
3265                     if (activeLeAudioDevices.get(0) != null) {
3266                         mLeAudioService.removeActiveDevice(true);
3267                     }
3268                 }
3269                 mA2dpService.setActiveDevice(device);
3270             }
3271         }
3272 
3273         if (mHearingAidService != null
3274                 && (device == null
3275                         || mHearingAidService.getConnectionPolicy(device)
3276                                 == CONNECTION_POLICY_ALLOWED)) {
3277             Log.i(TAG, "setActiveDevice: Setting active Hearing Aid " + device);
3278             if (device == null) {
3279                 mHearingAidService.removeActiveDevice(false);
3280             } else {
3281                 mHearingAidService.setActiveDevice(device);
3282             }
3283         }
3284 
3285         return true;
3286     }
3287 
3288     /**
3289      * Checks if all supported classic audio profiles are active on this LE Audio device.
3290      *
3291      * @param leAudioDevice the remote device
3292      * @return {@code true} if all supported classic audio profiles are active on this device,
3293      *     {@code false} otherwise
3294      */
isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice)3295     public boolean isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice) {
3296         if (mLeAudioService == null) {
3297             return false;
3298         }
3299         boolean hfpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.HEADSET);
3300         boolean a2dpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.A2DP);
3301 
3302         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(leAudioDevice);
3303         if (hfpSupported && mHeadsetService != null) {
3304             BluetoothDevice activeHfpDevice = mHeadsetService.getActiveDevice();
3305             if (activeHfpDevice == null || !groupDevices.contains(activeHfpDevice)) {
3306                 return false;
3307             }
3308         }
3309         if (a2dpSupported && mA2dpService != null) {
3310             BluetoothDevice activeA2dpDevice = mA2dpService.getActiveDevice();
3311             if (activeA2dpDevice == null || !groupDevices.contains(activeA2dpDevice)) {
3312                 return false;
3313             }
3314         }
3315         return true;
3316     }
3317 
3318     /**
3319      * Get the active devices for the BluetoothProfile specified
3320      *
3321      * @param profile is the profile from which we want the active devices. Possible values are:
3322      *     {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}, {@link
3323      *     BluetoothProfile#HEARING_AID} {@link BluetoothProfile#LE_AUDIO}
3324      * @return A list of active bluetooth devices
3325      */
getActiveDevices(@ctiveDeviceProfile int profile)3326     public List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) {
3327         List<BluetoothDevice> activeDevices = new ArrayList<>();
3328 
3329         switch (profile) {
3330             case BluetoothProfile.HEADSET:
3331                 if (mHeadsetService == null) {
3332                     Log.e(TAG, "getActiveDevices: HeadsetService is null");
3333                 } else {
3334                     BluetoothDevice device = mHeadsetService.getActiveDevice();
3335                     if (device != null) {
3336                         activeDevices.add(device);
3337                     }
3338                     Log.i(TAG, "getActiveDevices: Headset device: " + device);
3339                 }
3340                 break;
3341             case BluetoothProfile.A2DP:
3342                 if (mA2dpService == null) {
3343                     Log.e(TAG, "getActiveDevices: A2dpService is null");
3344                 } else {
3345                     BluetoothDevice device = mA2dpService.getActiveDevice();
3346                     if (device != null) {
3347                         activeDevices.add(device);
3348                     }
3349                     Log.i(TAG, "getActiveDevices: A2dp device: " + device);
3350                 }
3351                 break;
3352             case BluetoothProfile.HEARING_AID:
3353                 if (mHearingAidService == null) {
3354                     Log.e(TAG, "getActiveDevices: HearingAidService is null");
3355                 } else {
3356                     activeDevices = mHearingAidService.getActiveDevices();
3357                     Log.i(
3358                             TAG,
3359                             "getActiveDevices: Hearing Aid devices:"
3360                                     + (" Left[" + activeDevices.get(0) + "] -")
3361                                     + (" Right[" + activeDevices.get(1) + "]"));
3362                 }
3363                 break;
3364             case BluetoothProfile.LE_AUDIO:
3365                 if (mLeAudioService == null) {
3366                     Log.e(TAG, "getActiveDevices: LeAudioService is null");
3367                 } else {
3368                     activeDevices = mLeAudioService.getActiveDevices();
3369                     Log.i(
3370                             TAG,
3371                             "getActiveDevices: LeAudio devices:"
3372                                     + (" Lead[" + activeDevices.get(0) + "] -")
3373                                     + (" member_1[" + activeDevices.get(1) + "]"));
3374                 }
3375                 break;
3376             default:
3377                 Log.e(TAG, "getActiveDevices: profile value is not valid");
3378         }
3379         return activeDevices;
3380     }
3381 
3382     /**
3383      * Attempts connection to all enabled and supported bluetooth profiles between the local and
3384      * remote device
3385      *
3386      * @param device is the remote device with which to connect these profiles
3387      * @return {@link BluetoothStatusCodes#SUCCESS} if all profiles connections are attempted, false
3388      *     if an error occurred
3389      */
connectAllEnabledProfiles(BluetoothDevice device)3390     public int connectAllEnabledProfiles(BluetoothDevice device) {
3391         if (!profileServicesRunning()) {
3392             Log.e(TAG, "connectAllEnabledProfiles: Not all profile services running");
3393             return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3394         }
3395 
3396         // Checks if any profiles are enabled or disabled and if so, only connect enabled profiles
3397         if (!isAllProfilesUnknown(device)) {
3398             return connectEnabledProfiles(device);
3399         }
3400 
3401         connectAllSupportedProfiles(device);
3402 
3403         return BluetoothStatusCodes.SUCCESS;
3404     }
3405 
3406     /** All profile toggles are disabled, so connects all supported profiles */
connectAllSupportedProfiles(BluetoothDevice device)3407     void connectAllSupportedProfiles(BluetoothDevice device) {
3408         int numProfilesConnected = 0;
3409 
3410         // Order matters, some devices do not accept A2DP connection before HFP connection
3411         if (mHeadsetService != null && isProfileSupported(device, BluetoothProfile.HEADSET)) {
3412             Log.i(TAG, "connectAllSupportedProfiles: Connecting Headset Profile");
3413             mHeadsetService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3414             numProfilesConnected++;
3415         }
3416         if (mHeadsetClientService != null
3417                 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT)) {
3418             Log.i(TAG, "connectAllSupportedProfiles: Connecting HFP");
3419             mHeadsetClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3420             numProfilesConnected++;
3421         }
3422         if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) {
3423             Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp");
3424             // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED
3425             mA2dpService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3426             numProfilesConnected++;
3427         }
3428         if (mA2dpSinkService != null && isProfileSupported(device, BluetoothProfile.A2DP_SINK)) {
3429             Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink");
3430             mA2dpSinkService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3431             numProfilesConnected++;
3432         }
3433         if (mMapClientService != null && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)) {
3434             Log.i(TAG, "connectAllSupportedProfiles: Connecting MAP");
3435             mMapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3436             numProfilesConnected++;
3437         }
3438         if (mHidHostService != null && isProfileSupported(device, BluetoothProfile.HID_HOST)) {
3439             Log.i(TAG, "connectAllSupportedProfiles: Connecting Hid Host Profile");
3440             mHidHostService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3441             numProfilesConnected++;
3442         }
3443         if (mPanService != null && isProfileSupported(device, BluetoothProfile.PAN)) {
3444             Log.i(TAG, "connectAllSupportedProfiles: Connecting Pan Profile");
3445             mPanService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3446             numProfilesConnected++;
3447         }
3448         if (mPbapClientService != null
3449                 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT)) {
3450             Log.i(TAG, "connectAllSupportedProfiles: Connecting Pbap");
3451             mPbapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3452             numProfilesConnected++;
3453         }
3454         if (mHearingAidService != null
3455                 && isProfileSupported(device, BluetoothProfile.HEARING_AID)) {
3456             if (mHapClientService != null
3457                     && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) {
3458                 Log.i(
3459                         TAG,
3460                         "connectAllSupportedProfiles: Hearing Access Client Profile is enabled at"
3461                                 + " the same time with Hearing Aid Profile, ignore Hearing Aid"
3462                                 + " Profile");
3463             } else {
3464                 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Aid Profile");
3465                 mHearingAidService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3466                 numProfilesConnected++;
3467             }
3468         }
3469         if (mHapClientService != null && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) {
3470             Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Access Client Profile");
3471             mHapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3472             numProfilesConnected++;
3473         }
3474         if (mVolumeControlService != null
3475                 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL)) {
3476             Log.i(TAG, "connectAllSupportedProfiles: Connecting Volume Control Profile");
3477             mVolumeControlService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3478             numProfilesConnected++;
3479         }
3480         if (mCsipSetCoordinatorService != null
3481                 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR)) {
3482             Log.i(TAG, "connectAllSupportedProfiles: Connecting Coordinated Set Profile");
3483             mCsipSetCoordinatorService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3484             numProfilesConnected++;
3485         }
3486         if (mLeAudioService != null && isProfileSupported(device, BluetoothProfile.LE_AUDIO)) {
3487             Log.i(TAG, "connectAllSupportedProfiles: Connecting LeAudio profile (BAP)");
3488             mLeAudioService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3489             numProfilesConnected++;
3490         }
3491         if (mBassClientService != null
3492                 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) {
3493             Log.i(TAG, "connectAllSupportedProfiles: Connecting LE Broadcast Assistant Profile");
3494             mBassClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3495             numProfilesConnected++;
3496         }
3497         if (mBatteryService != null && isProfileSupported(device, BluetoothProfile.BATTERY)) {
3498             Log.i(TAG, "connectAllSupportedProfiles: Connecting Battery Service");
3499             mBatteryService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
3500             numProfilesConnected++;
3501         }
3502 
3503         Log.i(
3504                 TAG,
3505                 "connectAllSupportedProfiles: Number of Profiles Connected: "
3506                         + numProfilesConnected);
3507     }
3508 
3509     /**
3510      * Disconnects all enabled and supported bluetooth profiles between the local and remote device
3511      *
3512      * @param device is the remote device with which to disconnect these profiles
3513      * @return true if all profiles successfully disconnected, false if an error occurred
3514      */
disconnectAllEnabledProfiles(BluetoothDevice device)3515     public int disconnectAllEnabledProfiles(BluetoothDevice device) {
3516         if (!profileServicesRunning()) {
3517             Log.e(TAG, "disconnectAllEnabledProfiles: Not all profile services bound");
3518             return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3519         }
3520 
3521         if (mHeadsetService != null
3522                 && (mHeadsetService.getConnectionState(device) == STATE_CONNECTED
3523                         || mHeadsetService.getConnectionState(device) == STATE_CONNECTING)) {
3524             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Headset Profile");
3525             mHeadsetService.disconnect(device);
3526         }
3527         if (mHeadsetClientService != null
3528                 && (mHeadsetClientService.getConnectionState(device) == STATE_CONNECTED
3529                         || mHeadsetClientService.getConnectionState(device) == STATE_CONNECTING)) {
3530             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP");
3531             mHeadsetClientService.disconnect(device);
3532         }
3533         if (mA2dpService != null
3534                 && (mA2dpService.getConnectionState(device) == STATE_CONNECTED
3535                         || mA2dpService.getConnectionState(device) == STATE_CONNECTING)) {
3536             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp");
3537             mA2dpService.disconnect(device);
3538         }
3539         if (mA2dpSinkService != null
3540                 && (mA2dpSinkService.getConnectionState(device) == STATE_CONNECTED
3541                         || mA2dpSinkService.getConnectionState(device) == STATE_CONNECTING)) {
3542             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink");
3543             mA2dpSinkService.disconnect(device);
3544         }
3545         if (mMapClientService != null
3546                 && (mMapClientService.getConnectionState(device) == STATE_CONNECTED
3547                         || mMapClientService.getConnectionState(device) == STATE_CONNECTING)) {
3548             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP Client");
3549             mMapClientService.disconnect(device);
3550         }
3551         if (mMapService != null
3552                 && (mMapService.getConnectionState(device) == STATE_CONNECTED
3553                         || mMapService.getConnectionState(device) == STATE_CONNECTING)) {
3554             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP");
3555             mMapService.disconnect(device);
3556         }
3557         if (mHidDeviceService != null
3558                 && (mHidDeviceService.getConnectionState(device) == STATE_CONNECTED
3559                         || mHidDeviceService.getConnectionState(device) == STATE_CONNECTING)) {
3560             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Device Profile");
3561             mHidDeviceService.disconnect(device);
3562         }
3563         if (mHidHostService != null
3564                 && (mHidHostService.getConnectionState(device) == STATE_CONNECTED
3565                         || mHidHostService.getConnectionState(device) == STATE_CONNECTING)) {
3566             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Host Profile");
3567             mHidHostService.disconnect(device);
3568         }
3569         if (mPanService != null
3570                 && (mPanService.getConnectionState(device) == STATE_CONNECTED
3571                         || mPanService.getConnectionState(device) == STATE_CONNECTING)) {
3572             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pan Profile");
3573             mPanService.disconnect(device);
3574         }
3575         if (mPbapClientService != null
3576                 && (mPbapClientService.getConnectionState(device) == STATE_CONNECTED
3577                         || mPbapClientService.getConnectionState(device) == STATE_CONNECTING)) {
3578             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Client");
3579             mPbapClientService.disconnect(device);
3580         }
3581         if (mPbapService != null
3582                 && (mPbapService.getConnectionState(device) == STATE_CONNECTED
3583                         || mPbapService.getConnectionState(device) == STATE_CONNECTING)) {
3584             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Server");
3585             mPbapService.disconnect(device);
3586         }
3587         if (mHearingAidService != null
3588                 && (mHearingAidService.getConnectionState(device) == STATE_CONNECTED
3589                         || mHearingAidService.getConnectionState(device) == STATE_CONNECTING)) {
3590             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Aid Profile");
3591             mHearingAidService.disconnect(device);
3592         }
3593         if (mHapClientService != null
3594                 && (mHapClientService.getConnectionState(device) == STATE_CONNECTED
3595                         || mHapClientService.getConnectionState(device) == STATE_CONNECTING)) {
3596             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Access Profile Client");
3597             mHapClientService.disconnect(device);
3598         }
3599         if (mVolumeControlService != null
3600                 && (mVolumeControlService.getConnectionState(device) == STATE_CONNECTED
3601                         || mVolumeControlService.getConnectionState(device) == STATE_CONNECTING)) {
3602             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Volume Control Profile");
3603             mVolumeControlService.disconnect(device);
3604         }
3605         if (mSapService != null
3606                 && (mSapService.getConnectionState(device) == STATE_CONNECTED
3607                         || mSapService.getConnectionState(device) == STATE_CONNECTING)) {
3608             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Sap Profile");
3609             mSapService.disconnect(device);
3610         }
3611         if (mCsipSetCoordinatorService != null
3612                 && (mCsipSetCoordinatorService.getConnectionState(device) == STATE_CONNECTED
3613                         || mCsipSetCoordinatorService.getConnectionState(device)
3614                                 == STATE_CONNECTING)) {
3615             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Coordinator Set Profile");
3616             mCsipSetCoordinatorService.disconnect(device);
3617         }
3618         if (mLeAudioService != null
3619                 && (mLeAudioService.getConnectionState(device) == STATE_CONNECTED
3620                         || mLeAudioService.getConnectionState(device) == STATE_CONNECTING)) {
3621             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting LeAudio profile (BAP)");
3622             mLeAudioService.disconnect(device);
3623         }
3624         if (mBassClientService != null
3625                 && (mBassClientService.getConnectionState(device) == STATE_CONNECTED
3626                         || mBassClientService.getConnectionState(device) == STATE_CONNECTING)) {
3627             Log.i(
3628                     TAG,
3629                     "disconnectAllEnabledProfiles: Disconnecting "
3630                             + "LE Broadcast Assistant Profile");
3631             mBassClientService.disconnect(device);
3632         }
3633         if (mBatteryService != null
3634                 && (mBatteryService.getConnectionState(device) == STATE_CONNECTED
3635                         || mBatteryService.getConnectionState(device) == STATE_CONNECTING)) {
3636             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting " + "Battery Service");
3637             mBatteryService.disconnect(device);
3638         }
3639 
3640         return BluetoothStatusCodes.SUCCESS;
3641     }
3642 
3643     /**
3644      * Same as API method {@link BluetoothDevice#getName()}
3645      *
3646      * @param device remote device of interest
3647      * @return remote device name
3648      */
getRemoteName(BluetoothDevice device)3649     public String getRemoteName(BluetoothDevice device) {
3650         return mRemoteDevices.getName(device);
3651     }
3652 
getRemoteClass(BluetoothDevice device)3653     public int getRemoteClass(BluetoothDevice device) {
3654         return mRemoteDevices.getBluetoothClass(device);
3655     }
3656 
3657     /**
3658      * Get UUIDs for service supported by a remote device
3659      *
3660      * @param device the remote device that we want to get UUIDs from
3661      * @return the uuids of the remote device
3662      */
getRemoteUuids(BluetoothDevice device)3663     public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
3664         return mRemoteDevices.getUuids(device);
3665     }
3666 
aclStateChangeBroadcastCallback( RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> cb)3667     void aclStateChangeBroadcastCallback(
3668             RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> cb) {
3669         int n = mBluetoothConnectionCallbacks.beginBroadcast();
3670         Log.d(TAG, "aclStateChangeBroadcastCallback() - Broadcasting to " + n + " receivers.");
3671         for (int i = 0; i < n; i++) {
3672             cb.accept(mBluetoothConnectionCallbacks.getBroadcastItem(i));
3673         }
3674         mBluetoothConnectionCallbacks.finishBroadcast();
3675     }
3676 
3677     /**
3678      * Converts HCI disconnect reasons to Android disconnect reasons.
3679      *
3680      * <p>The HCI Error Codes used for ACL disconnect reasons propagated up from native code were
3681      * copied from: packages/modules/Bluetooth/system/stack/include/hci_error_code.h
3682      *
3683      * <p>These error codes are specified and described in Bluetooth Core Spec v5.1, Vol 2, Part D.
3684      *
3685      * @param hciReason is the raw HCI disconnect reason from native.
3686      * @return the Android disconnect reason for apps.
3687      */
3688     static @BluetoothAdapter.BluetoothConnectionCallback.DisconnectReason int
hciToAndroidDisconnectReason(int hciReason)3689             hciToAndroidDisconnectReason(int hciReason) {
3690         switch (hciReason) {
3691             case /*HCI_SUCCESS*/ 0x00:
3692             case /*HCI_ERR_UNSPECIFIED*/ 0x1F:
3693             case /*HCI_ERR_UNDEFINED*/ 0xff:
3694                 return BluetoothStatusCodes.ERROR_UNKNOWN;
3695             case /*HCI_ERR_ILLEGAL_COMMAND*/ 0x01:
3696             case /*HCI_ERR_NO_CONNECTION*/ 0x02:
3697             case /*HCI_ERR_HW_FAILURE*/ 0x03:
3698             case /*HCI_ERR_DIFF_TRANSACTION_COLLISION*/ 0x2A:
3699             case /*HCI_ERR_ROLE_SWITCH_PENDING*/ 0x32:
3700             case /*HCI_ERR_ROLE_SWITCH_FAILED*/ 0x35:
3701                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL;
3702             case /*HCI_ERR_PAGE_TIMEOUT*/ 0x04:
3703             case /*HCI_ERR_CONNECTION_TOUT*/ 0x08:
3704             case /*HCI_ERR_HOST_TIMEOUT*/ 0x10:
3705             case /*HCI_ERR_LMP_RESPONSE_TIMEOUT*/ 0x22:
3706             case /*HCI_ERR_ADVERTISING_TIMEOUT*/ 0x3C:
3707             case /*HCI_ERR_CONN_FAILED_ESTABLISHMENT*/ 0x3E:
3708                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT;
3709             case /*HCI_ERR_AUTH_FAILURE*/ 0x05:
3710             case /*HCI_ERR_KEY_MISSING*/ 0x06:
3711             case /*HCI_ERR_HOST_REJECT_SECURITY*/ 0x0E:
3712             case /*HCI_ERR_REPEATED_ATTEMPTS*/ 0x17:
3713             case /*HCI_ERR_PAIRING_NOT_ALLOWED*/ 0x18:
3714             case /*HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE*/ 0x25:
3715             case /*HCI_ERR_UNIT_KEY_USED*/ 0x26:
3716             case /*HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED*/ 0x29:
3717             case /*HCI_ERR_INSUFFICIENT_SECURITY*/ 0x2F:
3718             case /*HCI_ERR_HOST_BUSY_PAIRING*/ 0x38:
3719                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY;
3720             case /*HCI_ERR_MEMORY_FULL*/ 0x07:
3721             case /*HCI_ERR_MAX_NUM_OF_CONNECTIONS*/ 0x09:
3722             case /*HCI_ERR_MAX_NUM_OF_SCOS*/ 0x0A:
3723             case /*HCI_ERR_COMMAND_DISALLOWED*/ 0x0C:
3724             case /*HCI_ERR_HOST_REJECT_RESOURCES*/ 0x0D:
3725             case /*HCI_ERR_LIMIT_REACHED*/ 0x43:
3726                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED;
3727             case /*HCI_ERR_CONNECTION_EXISTS*/ 0x0B:
3728                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS;
3729             case /*HCI_ERR_HOST_REJECT_DEVICE*/ 0x0F:
3730                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY;
3731             case /*HCI_ERR_ILLEGAL_PARAMETER_FMT*/ 0x12:
3732                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS;
3733             case /*HCI_ERR_PEER_USER*/ 0x13:
3734                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST;
3735             case /*HCI_ERR_REMOTE_POWER_OFF*/ 0x15:
3736                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST;
3737             case /*HCI_ERR_CONN_CAUSE_LOCAL_HOST*/ 0x16:
3738                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST;
3739             case /*HCI_ERR_UNSUPPORTED_REM_FEATURE*/ 0x1A:
3740                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE;
3741             case /*HCI_ERR_UNACCEPT_CONN_INTERVAL*/ 0x3B:
3742                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS;
3743             default:
3744                 Log.e(TAG, "Invalid HCI disconnect reason: " + hciReason);
3745                 return BluetoothStatusCodes.ERROR_UNKNOWN;
3746         }
3747     }
3748 
logUserBondResponse(BluetoothDevice device, boolean accepted, AttributionSource source)3749     void logUserBondResponse(BluetoothDevice device, boolean accepted, AttributionSource source) {
3750         final long token = Binder.clearCallingIdentity();
3751         try {
3752             MetricsLogger.getInstance()
3753                     .logBluetoothEvent(
3754                             device,
3755                             BluetoothStatsLog
3756                                     .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__USER_CONF_REQUEST,
3757                             accepted
3758                                     ? BluetoothStatsLog
3759                                             .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS
3760                                     : BluetoothStatsLog
3761                                             .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL,
3762                             source.getUid());
3763         } finally {
3764             Binder.restoreCallingIdentity(token);
3765         }
3766     }
3767 
getPhonebookAccessPermission(BluetoothDevice device)3768     public int getPhonebookAccessPermission(BluetoothDevice device) {
3769         return getDeviceAccessFromPrefs(device, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE);
3770     }
3771 
getMessageAccessPermission(BluetoothDevice device)3772     public int getMessageAccessPermission(BluetoothDevice device) {
3773         return getDeviceAccessFromPrefs(device, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE);
3774     }
3775 
getSimAccessPermission(BluetoothDevice device)3776     public int getSimAccessPermission(BluetoothDevice device) {
3777         return getDeviceAccessFromPrefs(device, SIM_ACCESS_PERMISSION_PREFERENCE_FILE);
3778     }
3779 
getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile)3780     int getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile) {
3781         SharedPreferences prefs = getSharedPreferences(prefFile, Context.MODE_PRIVATE);
3782         if (!prefs.contains(device.getAddress())) {
3783             return BluetoothDevice.ACCESS_UNKNOWN;
3784         }
3785         return prefs.getBoolean(device.getAddress(), false)
3786                 ? BluetoothDevice.ACCESS_ALLOWED
3787                 : BluetoothDevice.ACCESS_REJECTED;
3788     }
3789 
setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile)3790     void setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile) {
3791         SharedPreferences pref = getSharedPreferences(prefFile, Context.MODE_PRIVATE);
3792         SharedPreferences.Editor editor = pref.edit();
3793         if (value == BluetoothDevice.ACCESS_UNKNOWN) {
3794             editor.remove(device.getAddress());
3795         } else {
3796             editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
3797         }
3798         editor.apply();
3799     }
3800 
setPhonebookAccessPermission(BluetoothDevice device, int value)3801     public void setPhonebookAccessPermission(BluetoothDevice device, int value) {
3802         Log.d(
3803                 TAG,
3804                 "setPhonebookAccessPermission device="
3805                         + ((device == null) ? "null" : device.getAnonymizedAddress())
3806                         + ", value="
3807                         + value
3808                         + ", callingUid="
3809                         + Binder.getCallingUid());
3810         setDeviceAccessFromPrefs(device, value, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE);
3811     }
3812 
setMessageAccessPermission(BluetoothDevice device, int value)3813     public void setMessageAccessPermission(BluetoothDevice device, int value) {
3814         setDeviceAccessFromPrefs(device, value, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE);
3815     }
3816 
setSimAccessPermission(BluetoothDevice device, int value)3817     public void setSimAccessPermission(BluetoothDevice device, int value) {
3818         setDeviceAccessFromPrefs(device, value, SIM_ACCESS_PERMISSION_PREFERENCE_FILE);
3819     }
3820 
isRpaOffloadSupported()3821     public boolean isRpaOffloadSupported() {
3822         return mAdapterProperties.isRpaOffloadSupported();
3823     }
3824 
getNumOfOffloadedIrkSupported()3825     public int getNumOfOffloadedIrkSupported() {
3826         return mAdapterProperties.getNumOfOffloadedIrkSupported();
3827     }
3828 
getNumOfOffloadedScanFilterSupported()3829     public int getNumOfOffloadedScanFilterSupported() {
3830         return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
3831     }
3832 
getOffloadedScanResultStorage()3833     public int getOffloadedScanResultStorage() {
3834         return mAdapterProperties.getOffloadedScanResultStorage();
3835     }
3836 
isLe2MPhySupported()3837     public boolean isLe2MPhySupported() {
3838         return mAdapterProperties.isLe2MPhySupported();
3839     }
3840 
isLeCodedPhySupported()3841     public boolean isLeCodedPhySupported() {
3842         return mAdapterProperties.isLeCodedPhySupported();
3843     }
3844 
isLeExtendedAdvertisingSupported()3845     public boolean isLeExtendedAdvertisingSupported() {
3846         return mAdapterProperties.isLeExtendedAdvertisingSupported();
3847     }
3848 
isLePeriodicAdvertisingSupported()3849     public boolean isLePeriodicAdvertisingSupported() {
3850         return mAdapterProperties.isLePeriodicAdvertisingSupported();
3851     }
3852 
3853     /**
3854      * Check if the LE audio broadcast source feature is supported.
3855      *
3856      * @return true, if the LE audio broadcast source is supported
3857      */
isLeAudioBroadcastSourceSupported()3858     public boolean isLeAudioBroadcastSourceSupported() {
3859         return mAdapterProperties.isLePeriodicAdvertisingSupported()
3860                 && mAdapterProperties.isLeExtendedAdvertisingSupported()
3861                 && mAdapterProperties.isLeIsochronousBroadcasterSupported();
3862     }
3863 
3864     /**
3865      * Check if the LE audio broadcast assistant feature is supported.
3866      *
3867      * @return true, if the LE audio broadcast assistant is supported
3868      */
isLeAudioBroadcastAssistantSupported()3869     public boolean isLeAudioBroadcastAssistantSupported() {
3870         return mAdapterProperties.isLePeriodicAdvertisingSupported()
3871                 && mAdapterProperties.isLeExtendedAdvertisingSupported()
3872                 && (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported()
3873                         || mAdapterProperties
3874                                 .isLePeriodicAdvertisingSyncTransferRecipientSupported());
3875     }
3876 
3877     /**
3878      * Check if the LE channel sounding feature is supported.
3879      *
3880      * @return true, if the LE channel sounding is supported
3881      */
isLeChannelSoundingSupported()3882     public boolean isLeChannelSoundingSupported() {
3883         return mAdapterProperties.isLeChannelSoundingSupported();
3884     }
3885 
getSupportedProfilesBitMask()3886     public long getSupportedProfilesBitMask() {
3887         return Config.getSupportedProfilesBitMask();
3888     }
3889 
3890     /**
3891      * Check if the LE audio CIS central feature is supported.
3892      *
3893      * @return true, if the LE audio CIS central is supported
3894      */
isLeConnectedIsochronousStreamCentralSupported()3895     public boolean isLeConnectedIsochronousStreamCentralSupported() {
3896         return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported();
3897     }
3898 
getLeMaximumAdvertisingDataLength()3899     public int getLeMaximumAdvertisingDataLength() {
3900         return mAdapterProperties.getLeMaximumAdvertisingDataLength();
3901     }
3902 
3903     /**
3904      * Get the maximum number of connected audio devices.
3905      *
3906      * @return the maximum number of connected audio devices
3907      */
getMaxConnectedAudioDevices()3908     public int getMaxConnectedAudioDevices() {
3909         return mAdapterProperties.getMaxConnectedAudioDevices();
3910     }
3911 
3912     /**
3913      * Check whether A2DP offload is enabled.
3914      *
3915      * @return true if A2DP offload is enabled
3916      */
isA2dpOffloadEnabled()3917     public boolean isA2dpOffloadEnabled() {
3918         return mAdapterProperties.isA2dpOffloadEnabled();
3919     }
3920 
3921     /** Register a bluetooth state callback */
registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback)3922     public void registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback) {
3923         mLocalCallbacks.put(callback, executor);
3924     }
3925 
3926     /** Unregister a bluetooth state callback */
unregisterBluetoothStateCallback(BluetoothStateCallback callback)3927     public void unregisterBluetoothStateCallback(BluetoothStateCallback callback) {
3928         mLocalCallbacks.remove(callback);
3929     }
3930 
registerRemoteCallback(IBluetoothCallback callback)3931     void registerRemoteCallback(IBluetoothCallback callback) {
3932         mSystemServerCallbacks.register(callback);
3933     }
3934 
unregisterRemoteCallback(IBluetoothCallback callback)3935     void unregisterRemoteCallback(IBluetoothCallback callback) {
3936         mSystemServerCallbacks.unregister(callback);
3937     }
3938 
bleOnToOn()3939     void bleOnToOn() {
3940         mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);
3941     }
3942 
bleOnToOff()3943     void bleOnToOff() {
3944         mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
3945     }
3946 
factoryReset()3947     boolean factoryReset() {
3948         mDatabaseManager.factoryReset();
3949 
3950         if (mBluetoothKeystoreService != null) {
3951             mBluetoothKeystoreService.factoryReset();
3952         }
3953 
3954         if (mBtCompanionManager != null) {
3955             mBtCompanionManager.factoryReset();
3956         }
3957 
3958         if (Flags.gattClearCacheOnFactoryReset()) {
3959             clearStorage();
3960         }
3961 
3962         return mNativeInterface.factoryReset();
3963     }
3964 
getScanMode()3965     int getScanMode() {
3966         return mScanMode;
3967     }
3968 
setScanMode(int mode, String from)3969     boolean setScanMode(int mode, String from) {
3970         mScanModeChanges.add(from + ": " + scanModeName(mode));
3971         if (!mNativeInterface.setScanMode(convertScanModeToHal(mode))) {
3972             return false;
3973         }
3974         mScanMode = mode;
3975         Intent intent =
3976                 new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)
3977                         .putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode)
3978                         .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3979         sendBroadcast(intent, BLUETOOTH_SCAN, Utils.getTempBroadcastOptions().toBundle());
3980         return true;
3981     }
3982 
reportActivityInfo()3983     BluetoothActivityEnergyInfo reportActivityInfo() {
3984         if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON
3985                 || !mAdapterProperties.isActivityAndEnergyReportingSupported()) {
3986             return null;
3987         }
3988 
3989         // Pull the data. The callback will notify mEnergyInfoLock.
3990         mNativeInterface.readEnergyInfo();
3991 
3992         synchronized (mEnergyInfoLock) {
3993             long now = System.currentTimeMillis();
3994             final long deadline = now + CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS;
3995             while (now < deadline) {
3996                 try {
3997                     mEnergyInfoLock.wait(deadline - now);
3998                     break;
3999                 } catch (InterruptedException e) {
4000                     now = System.currentTimeMillis();
4001                 }
4002             }
4003 
4004             final BluetoothActivityEnergyInfo info =
4005                     new BluetoothActivityEnergyInfo(
4006                             SystemClock.elapsedRealtime(),
4007                             mStackReportedState,
4008                             mTxTimeTotalMs,
4009                             mRxTimeTotalMs,
4010                             mIdleTimeTotalMs,
4011                             mEnergyUsedTotalVoltAmpSecMicro);
4012 
4013             // Copy the traffic objects whose byte counts are > 0
4014             final List<UidTraffic> result = new ArrayList<>();
4015             for (int i = 0; i < mUidTraffic.size(); i++) {
4016                 final UidTraffic traffic = mUidTraffic.valueAt(i);
4017                 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
4018                     result.add(traffic.clone());
4019                 }
4020             }
4021 
4022             info.setUidTraffic(result);
4023 
4024             return info;
4025         }
4026     }
4027 
getTotalNumOfTrackableAdvertisements()4028     public int getTotalNumOfTrackableAdvertisements() {
4029         return mAdapterProperties.getTotalNumOfTrackableAdvertisements();
4030     }
4031 
4032     /**
4033      * Return if offloaded TDS filter is supported.
4034      *
4035      * @return {@code BluetoothStatusCodes.FEATURE_SUPPORTED} if supported
4036      */
getOffloadedTransportDiscoveryDataScanSupported()4037     public int getOffloadedTransportDiscoveryDataScanSupported() {
4038         if (mAdapterProperties.isOffloadedTransportDiscoveryDataScanSupported()) {
4039             return BluetoothStatusCodes.FEATURE_SUPPORTED;
4040         }
4041         return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
4042     }
4043 
getBluetoothGatt()4044     IBinder getBluetoothGatt() {
4045         return mGattService == null ? null : mGattService.getBinder();
4046     }
4047 
getBluetoothGattService()4048     public GattService getBluetoothGattService() {
4049         return mGattService;
4050     }
4051 
getBluetoothScan()4052     IBinder getBluetoothScan() {
4053         ScanController controller = getBluetoothScanController();
4054         return controller == null ? null : controller.getBinder();
4055     }
4056 
4057     @Nullable
getBluetoothScanController()4058     public ScanController getBluetoothScanController() {
4059         if (Flags.onlyStartScanDuringBleOn()) {
4060             return mScanController;
4061         } else {
4062             return mGattService == null ? null : mGattService.getScanController();
4063         }
4064     }
4065 
4066     @Nullable
getBluetoothAdvertise()4067     IBinder getBluetoothAdvertise() {
4068         return mGattService == null ? null : mGattService.getBluetoothAdvertise();
4069     }
4070 
4071     @Nullable
getDistanceMeasurement()4072     IBinder getDistanceMeasurement() {
4073         return mGattService == null ? null : mGattService.getDistanceMeasurement();
4074     }
4075 
4076     @RequiresPermission(BLUETOOTH_CONNECT)
unregAllGattClient(AttributionSource source)4077     void unregAllGattClient(AttributionSource source) {
4078         if (mGattService != null) {
4079             mGattService.unregAll(source);
4080         }
4081     }
4082 
getProfile(int profileId)4083     IBinder getProfile(int profileId) {
4084         if (getState() == BluetoothAdapter.STATE_TURNING_ON) {
4085             return null;
4086         }
4087 
4088         // LE_AUDIO_BROADCAST is not associated with a service and use LE_AUDIO's Binder
4089         if (profileId == BluetoothProfile.LE_AUDIO_BROADCAST) {
4090             profileId = BluetoothProfile.LE_AUDIO;
4091         }
4092 
4093         ProfileService profile = mStartedProfiles.get(profileId);
4094         if (profile != null) {
4095             return profile.getBinder();
4096         } else {
4097             return null;
4098         }
4099     }
4100 
isMediaProfileConnected()4101     boolean isMediaProfileConnected() {
4102         if (mA2dpService != null && mA2dpService.getConnectedDevices().size() > 0) {
4103             Log.d(TAG, "isMediaProfileConnected. A2dp is connected");
4104             return true;
4105         } else if (mHearingAidService != null
4106                 && mHearingAidService.getConnectedDevices().size() > 0) {
4107             Log.d(TAG, "isMediaProfileConnected. HearingAid is connected");
4108             return true;
4109         } else if (mLeAudioService != null && mLeAudioService.getConnectedDevices().size() > 0) {
4110             Log.d(TAG, "isMediaProfileConnected. LeAudio is connected");
4111             return true;
4112         } else {
4113             Log.d(
4114                     TAG,
4115                     "isMediaProfileConnected: no Media connected."
4116                             + (" A2dp=" + mA2dpService)
4117                             + (" HearingAid=" + mHearingAidService)
4118                             + (" LeAudio=" + mLeAudioService));
4119             return false;
4120         }
4121     }
4122 
updatePhonePolicyOnAclConnect(BluetoothDevice device)4123     void updatePhonePolicyOnAclConnect(BluetoothDevice device) {
4124         mPhonePolicy.ifPresent(policy -> policy.handleAclConnected(device));
4125     }
4126 
4127     /**
4128      * Notify {@link BluetoothProfile} when ACL connection disconnects from {@link BluetoothDevice}
4129      * for a given {@code transport}.
4130      */
notifyAclDisconnected(BluetoothDevice device, int transport)4131     public void notifyAclDisconnected(BluetoothDevice device, int transport) {
4132         if (mMapService != null && mMapService.isAvailable()) {
4133             mMapService.aclDisconnected(device);
4134         }
4135         if (mMapClientService != null && mMapClientService.isAvailable()) {
4136             mMapClientService.aclDisconnected(device, transport);
4137         }
4138         if (mSapService != null && mSapService.isAvailable()) {
4139             mSapService.aclDisconnected(device);
4140         }
4141         if (mPbapClientService != null && mPbapClientService.isAvailable()) {
4142             mPbapClientService.aclDisconnected(device, transport);
4143         }
4144     }
4145 
4146     /**
4147      * Notify GATT of a Bluetooth profile's connection state change for a given {@link
4148      * BluetoothProfile}.
4149      */
notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState)4150     public void notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState) {
4151         if (mGattService == null) {
4152             Log.w(TAG, "GATT Service is not running!");
4153             return;
4154         }
4155         ScanController controller = getBluetoothScanController();
4156         if (controller != null) {
4157             controller.notifyProfileConnectionStateChange(profile, fromState, toState);
4158         }
4159     }
4160 
4161     /**
4162      * Handle Bluetooth app state when connection state changes for a given {@code profile}.
4163      *
4164      * <p>Currently this function is limited to handling Phone policy but the eventual goal is to
4165      * move all connection logic here.
4166      */
handleProfileConnectionStateChange( int profile, BluetoothDevice device, int fromState, int toState)4167     public void handleProfileConnectionStateChange(
4168             int profile, BluetoothDevice device, int fromState, int toState) {
4169         mPhonePolicy.ifPresent(
4170                 policy ->
4171                         policy.profileConnectionStateChanged(profile, device, fromState, toState));
4172     }
4173 
4174     /** Handle Bluetooth app state when active device changes for a given {@code profile}. */
handleActiveDeviceChange(int profile, BluetoothDevice device)4175     public void handleActiveDeviceChange(int profile, BluetoothDevice device) {
4176         mActiveDeviceManager.profileActiveDeviceChanged(profile, device);
4177         mSilenceDeviceManager.profileActiveDeviceChanged(profile, device);
4178         mPhonePolicy.ifPresent(policy -> policy.profileActiveDeviceChanged(profile, device));
4179     }
4180 
4181     /** Notify MAP and Pbap when a new sdp search record is found. */
sendSdpSearchRecord( BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid)4182     public void sendSdpSearchRecord(
4183             BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) {
4184         if (mMapService != null && mMapService.isAvailable()) {
4185             mMapService.receiveSdpSearchRecord(status, record, uuid);
4186         }
4187         if (mMapClientService != null && mMapClientService.isAvailable()) {
4188             mMapClientService.receiveSdpSearchRecord(device, status, record, uuid);
4189         }
4190         if (mPbapClientService != null && mPbapClientService.isAvailable()) {
4191             mPbapClientService.receiveSdpSearchRecord(device, status, record, uuid);
4192         }
4193     }
4194 
4195     /** Handle Bluetooth profiles when bond state changes with a {@link BluetoothDevice} */
handleBondStateChanged(BluetoothDevice device, int fromState, int toState)4196     public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) {
4197         if (mHeadsetService != null && mHeadsetService.isAvailable()) {
4198             mHeadsetService.handleBondStateChanged(device, fromState, toState);
4199         }
4200         if (mA2dpService != null && mA2dpService.isAvailable()) {
4201             mA2dpService.handleBondStateChanged(device, fromState, toState);
4202         }
4203         if (mLeAudioService != null && mLeAudioService.isAvailable()) {
4204             mLeAudioService.handleBondStateChanged(device, fromState, toState);
4205         }
4206         if (mHearingAidService != null && mHearingAidService.isAvailable()) {
4207             mHearingAidService.handleBondStateChanged(device, fromState, toState);
4208         }
4209         if (mHapClientService != null && mHapClientService.isAvailable()) {
4210             mHapClientService.handleBondStateChanged(device, fromState, toState);
4211         }
4212         if (mBassClientService != null && mBassClientService.isAvailable()) {
4213             mBassClientService.handleBondStateChanged(device, fromState, toState);
4214         }
4215         if (mBatteryService != null && mBatteryService.isAvailable()) {
4216             mBatteryService.handleBondStateChanged(device, fromState, toState);
4217         }
4218         if (mVolumeControlService != null && mVolumeControlService.isAvailable()) {
4219             mVolumeControlService.handleBondStateChanged(device, fromState, toState);
4220         }
4221         if (mPbapService != null && mPbapService.isAvailable()) {
4222             mPbapService.handleBondStateChanged(device, fromState, toState);
4223         }
4224         if (mCsipSetCoordinatorService != null && mCsipSetCoordinatorService.isAvailable()) {
4225             mCsipSetCoordinatorService.handleBondStateChanged(device, fromState, toState);
4226         }
4227         mDatabaseManager.handleBondStateChanged(device, fromState, toState);
4228 
4229         if (toState == BOND_NONE) {
4230             // Remove the permissions for unbonded devices
4231             setMessageAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN);
4232             setPhonebookAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN);
4233             setSimAccessPermission(device, BluetoothDevice.ACCESS_UNKNOWN);
4234         }
4235     }
4236 
convertScanModeToHal(int mode)4237     static int convertScanModeToHal(int mode) {
4238         switch (mode) {
4239             case SCAN_MODE_NONE:
4240                 return AbstractionLayer.BT_SCAN_MODE_NONE;
4241             case SCAN_MODE_CONNECTABLE:
4242                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
4243             case SCAN_MODE_CONNECTABLE_DISCOVERABLE:
4244                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
4245         }
4246         return -1;
4247     }
4248 
convertScanModeFromHal(int mode)4249     static int convertScanModeFromHal(int mode) {
4250         switch (mode) {
4251             case AbstractionLayer.BT_SCAN_MODE_NONE:
4252                 return SCAN_MODE_NONE;
4253             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
4254                 return SCAN_MODE_CONNECTABLE;
4255             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
4256                 return SCAN_MODE_CONNECTABLE_DISCOVERABLE;
4257         }
4258         return -1;
4259     }
4260 
4261     // This function is called from JNI. It allows native code to acquire a single wake lock.
4262     // If the wake lock is already held, this function returns success. Although this function
4263     // only supports acquiring a single wake lock at a time right now, it will eventually be
4264     // extended to allow acquiring an arbitrary number of wake locks. The current interface
4265     // takes |lockName| as a parameter in anticipation of that implementation.
acquireWakeLock(String lockName)4266     boolean acquireWakeLock(String lockName) {
4267         synchronized (this) {
4268             if (mWakeLock == null) {
4269                 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
4270             }
4271 
4272             if (!mWakeLock.isHeld()) {
4273                 mWakeLock.acquire();
4274             }
4275         }
4276         return true;
4277     }
4278 
4279     // This function is called from JNI. It allows native code to release a wake lock acquired
4280     // by |acquireWakeLock|. If the wake lock is not held, this function returns failure.
4281     // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is
4282     // needed here. See the comment for |acquireWakeLock| for an explanation of the interface.
releaseWakeLock(String lockName)4283     boolean releaseWakeLock(String lockName) {
4284         synchronized (this) {
4285             if (mWakeLock == null) {
4286                 Log.e(TAG, "Repeated wake lock release; aborting release: " + lockName);
4287                 return false;
4288             }
4289 
4290             if (mWakeLock.isHeld()) {
4291                 mWakeLock.release();
4292             }
4293         }
4294         return true;
4295     }
4296 
energyInfoCallbackInternal( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)4297     void energyInfoCallbackInternal(
4298             int status,
4299             int ctrlState,
4300             long txTime,
4301             long rxTime,
4302             long idleTime,
4303             long energyUsed,
4304             UidTraffic[] data) {
4305         // Energy is product of mA, V and ms. If the chipset doesn't
4306         // report it, we have to compute it from time
4307         if (energyUsed == 0) {
4308             try {
4309                 final long txMah = Math.multiplyExact(txTime, getTxCurrentMa());
4310                 final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa());
4311                 final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa());
4312                 energyUsed =
4313                         (long)
4314                                 (Math.addExact(Math.addExact(txMah, rxMah), idleMah)
4315                                         * getOperatingVolt());
4316             } catch (ArithmeticException e) {
4317                 Log.wtf(TAG, "overflow in bluetooth energy callback", e);
4318                 // Energy is already 0 if the exception was thrown.
4319             }
4320         }
4321 
4322         synchronized (mEnergyInfoLock) {
4323             mStackReportedState = ctrlState;
4324             long totalTxTimeMs;
4325             long totalRxTimeMs;
4326             long totalIdleTimeMs;
4327             long totalEnergy;
4328             try {
4329                 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime);
4330                 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime);
4331                 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime);
4332                 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed);
4333             } catch (ArithmeticException e) {
4334                 // This could be because we accumulated a lot of time, or we got a very strange
4335                 // value from the controller (more likely). Discard this data.
4336                 Log.wtf(TAG, "overflow in bluetooth energy callback", e);
4337                 totalTxTimeMs = mTxTimeTotalMs;
4338                 totalRxTimeMs = mRxTimeTotalMs;
4339                 totalIdleTimeMs = mIdleTimeTotalMs;
4340                 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro;
4341             }
4342 
4343             mTxTimeTotalMs = totalTxTimeMs;
4344             mRxTimeTotalMs = totalRxTimeMs;
4345             mIdleTimeTotalMs = totalIdleTimeMs;
4346             mEnergyUsedTotalVoltAmpSecMicro = totalEnergy;
4347 
4348             for (UidTraffic traffic : data) {
4349                 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid());
4350                 if (existingTraffic == null) {
4351                     mUidTraffic.put(traffic.getUid(), traffic);
4352                 } else {
4353                     existingTraffic.addRxBytes(traffic.getRxBytes());
4354                     existingTraffic.addTxBytes(traffic.getTxBytes());
4355                 }
4356             }
4357             mEnergyInfoLock.notifyAll();
4358         }
4359     }
4360 
energyInfoCallback( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)4361     void energyInfoCallback(
4362             int status,
4363             int ctrlState,
4364             long txTime,
4365             long rxTime,
4366             long idleTime,
4367             long energyUsed,
4368             UidTraffic[] data) {
4369         energyInfoCallbackInternal(status, ctrlState, txTime, rxTime, idleTime, energyUsed, data);
4370         Log.v(
4371                 TAG,
4372                 "energyInfoCallback()"
4373                         + (" status = " + status)
4374                         + (" txTime = " + txTime)
4375                         + (" rxTime = " + rxTime)
4376                         + (" idleTime = " + idleTime)
4377                         + (" energyUsed = " + energyUsed)
4378                         + (" ctrlState = " + Utils.formatSimple("0x%08x", ctrlState))
4379                         + (" traffic = " + Arrays.toString(data)));
4380     }
4381 
4382     /** Update metadata change to registered listeners */
onMetadataChanged(BluetoothDevice device, int key, byte[] value)4383     public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
4384         mHandler.post(() -> onMetadataChangedInternal(device, key, value));
4385     }
4386 
onMetadataChangedInternal(BluetoothDevice device, int key, byte[] value)4387     private void onMetadataChangedInternal(BluetoothDevice device, int key, byte[] value) {
4388         String info = "onMetadataChangedInternal(" + device + ", " + key + ")";
4389 
4390         // pass just interesting metadata to native, to reduce spam
4391         if (key == BluetoothDevice.METADATA_LE_AUDIO) {
4392             mNativeInterface.metadataChanged(device, key, value);
4393         }
4394 
4395         RemoteCallbackList<IBluetoothMetadataListener> list = mMetadataListeners.get(device);
4396         if (list == null) {
4397             Log.d(TAG, info + ": No registered listener");
4398             return;
4399         }
4400         int n = list.beginBroadcast();
4401         Log.d(TAG, info + ": Broadcast to " + n + " receivers");
4402         for (int i = 0; i < n; i++) {
4403             try {
4404                 list.getBroadcastItem(i).onMetadataChanged(device, key, value);
4405             } catch (RemoteException e) {
4406                 Log.d(TAG, info + ": Callback #" + i + " failed (" + e + ")");
4407             }
4408         }
4409         list.finishBroadcast();
4410     }
4411 
getIdleCurrentMa()4412     private static int getIdleCurrentMa() {
4413         return BluetoothProperties.getHardwareIdleCurrentMa().orElse(0);
4414     }
4415 
getTxCurrentMa()4416     private static int getTxCurrentMa() {
4417         return BluetoothProperties.getHardwareTxCurrentMa().orElse(0);
4418     }
4419 
getRxCurrentMa()4420     private static int getRxCurrentMa() {
4421         return BluetoothProperties.getHardwareRxCurrentMa().orElse(0);
4422     }
4423 
getOperatingVolt()4424     private static double getOperatingVolt() {
4425         return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0;
4426     }
4427 
scanModeName(int scanMode)4428     private static String scanModeName(int scanMode) {
4429         return switch (scanMode) {
4430             case SCAN_MODE_NONE -> "SCAN_MODE_NONE";
4431             case SCAN_MODE_CONNECTABLE -> "SCAN_MODE_CONNECTABLE";
4432             case SCAN_MODE_CONNECTABLE_DISCOVERABLE -> "SCAN_MODE_CONNECTABLE_DISCOVERABLE";
4433             default -> "Unknown Scan Mode " + scanMode;
4434         };
4435     }
4436 
4437     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)4438     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
4439         if (args.length == 0) {
4440             writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section.");
4441             writer.println("Use --print argument for dumpsys direct from AdapterService.");
4442             return;
4443         }
4444 
4445         if ("set-test-mode".equals(args[0])) {
4446             final boolean testModeEnabled = "enabled".equalsIgnoreCase(args[1]);
4447             for (ProfileService profile : mRunningProfiles) {
4448                 profile.setTestModeEnabled(testModeEnabled);
4449             }
4450             if (Flags.onlyStartScanDuringBleOn() && mScanController != null) {
4451                 mScanController.setTestModeEnabled(testModeEnabled);
4452             }
4453             mTestModeEnabled = testModeEnabled;
4454             return;
4455         }
4456 
4457         writer.println();
4458         mAdapterProperties.dump(fd, writer, args);
4459 
4460         writer.println("ScanMode: " + scanModeName(getScanMode()));
4461         StringBuilder sb = new StringBuilder();
4462         mScanModeChanges.dump(sb);
4463         writer.println(sb.toString());
4464         writer.println();
4465         writer.println("sSnoopLogSettingAtEnable = " + sSnoopLogSettingAtEnable);
4466         writer.println("sDefaultSnoopLogSettingAtEnable = " + sDefaultSnoopLogSettingAtEnable);
4467 
4468         writer.println();
4469         writer.println("Enabled Profile Services:");
4470         for (int profileId : Config.getSupportedProfiles()) {
4471             writer.println("  " + BluetoothProfile.getProfileName(profileId));
4472         }
4473         writer.println();
4474 
4475         writer.println("LE Gatt clients controlling AutoActiveMode:");
4476         for (Pair<Integer, BluetoothDevice> pair : mLeGattClientsControllingAutoActiveMode) {
4477             writer.println("   clientIf:" + pair.first + " " + pair.second);
4478         }
4479         writer.println();
4480 
4481         mAdapterStateMachine.dump(fd, writer, args);
4482 
4483         sb = new StringBuilder();
4484 
4485         mSilenceDeviceManager.dump(sb);
4486         mDatabaseManager.dump(sb);
4487 
4488         for (ProfileService profile : mRegisteredProfiles) {
4489             profile.dump(sb);
4490         }
4491         if (Flags.onlyStartScanDuringBleOn()) {
4492             ScanController scanController = mScanController;
4493             if (scanController != null) {
4494                 scanController.dumpRegisterId(sb);
4495                 scanController.dump(sb);
4496             }
4497         }
4498 
4499         writer.write(sb.toString());
4500 
4501         final int currentState = mAdapterProperties.getState();
4502         if (currentState == BluetoothAdapter.STATE_OFF
4503                 || currentState == BluetoothAdapter.STATE_BLE_TURNING_ON
4504                 || currentState == BluetoothAdapter.STATE_TURNING_OFF
4505                 || currentState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
4506             writer.println();
4507             writer.println("Impossible to dump native stack. state=" + nameForState(currentState));
4508             writer.println();
4509             writer.flush();
4510         } else {
4511             writer.flush();
4512             mNativeInterface.dump(fd, args);
4513         }
4514     }
4515 
4516     private final Object mDeviceConfigLock = new Object();
4517 
4518     /**
4519      * Predicate that can be applied to names to determine if a device is well-known to be used for
4520      * physical location.
4521      */
4522     @GuardedBy("mDeviceConfigLock")
4523     private Predicate<String> mLocationDenylistName = (v) -> false;
4524 
4525     /**
4526      * Predicate that can be applied to MAC addresses to determine if a device is well-known to be
4527      * used for physical location.
4528      */
4529     @GuardedBy("mDeviceConfigLock")
4530     private Predicate<byte[]> mLocationDenylistMac = (v) -> false;
4531 
4532     /**
4533      * Predicate that can be applied to Advertising Data payloads to determine if a device is
4534      * well-known to be used for physical location.
4535      */
4536     @GuardedBy("mDeviceConfigLock")
4537     private Predicate<byte[]> mLocationDenylistAdvertisingData = (v) -> false;
4538 
4539     @GuardedBy("mDeviceConfigLock")
4540     private int mScanQuotaCount = DeviceConfigListener.DEFAULT_SCAN_QUOTA_COUNT;
4541 
4542     @GuardedBy("mDeviceConfigLock")
4543     private long mScanQuotaWindowMillis = DeviceConfigListener.DEFAULT_SCAN_QUOTA_WINDOW_MILLIS;
4544 
4545     @GuardedBy("mDeviceConfigLock")
4546     private long mScanTimeoutMillis = DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS;
4547 
4548     @GuardedBy("mDeviceConfigLock")
4549     private int mScanUpgradeDurationMillis =
4550             DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS;
4551 
4552     @GuardedBy("mDeviceConfigLock")
4553     private int mScanDowngradeDurationMillis =
4554             DeviceConfigListener.DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS;
4555 
4556     @GuardedBy("mDeviceConfigLock")
4557     private int mScreenOffLowPowerWindowMillis =
4558             ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS;
4559 
4560     @GuardedBy("mDeviceConfigLock")
4561     private int mScreenOffLowPowerIntervalMillis =
4562             ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS;
4563 
4564     @GuardedBy("mDeviceConfigLock")
4565     private int mScreenOffBalancedWindowMillis =
4566             ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS;
4567 
4568     @GuardedBy("mDeviceConfigLock")
4569     private int mScreenOffBalancedIntervalMillis =
4570             ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS;
4571 
4572     @GuardedBy("mDeviceConfigLock")
4573     private String mLeAudioAllowList;
4574 
getLocationDenylistName()4575     public @NonNull Predicate<String> getLocationDenylistName() {
4576         synchronized (mDeviceConfigLock) {
4577             return mLocationDenylistName;
4578         }
4579     }
4580 
getLocationDenylistMac()4581     public @NonNull Predicate<byte[]> getLocationDenylistMac() {
4582         synchronized (mDeviceConfigLock) {
4583             return mLocationDenylistMac;
4584         }
4585     }
4586 
getLocationDenylistAdvertisingData()4587     public @NonNull Predicate<byte[]> getLocationDenylistAdvertisingData() {
4588         synchronized (mDeviceConfigLock) {
4589             return mLocationDenylistAdvertisingData;
4590         }
4591     }
4592 
4593     /** Returns scan quota count. */
getScanQuotaCount()4594     public int getScanQuotaCount() {
4595         synchronized (mDeviceConfigLock) {
4596             return mScanQuotaCount;
4597         }
4598     }
4599 
4600     /** Returns scan quota window in millis. */
getScanQuotaWindowMillis()4601     public long getScanQuotaWindowMillis() {
4602         synchronized (mDeviceConfigLock) {
4603             return mScanQuotaWindowMillis;
4604         }
4605     }
4606 
4607     /** Returns scan timeout in millis. */
getScanTimeoutMillis()4608     public long getScanTimeoutMillis() {
4609         synchronized (mDeviceConfigLock) {
4610             return mScanTimeoutMillis;
4611         }
4612     }
4613 
4614     /** Returns scan upgrade duration in millis. */
getScanUpgradeDurationMillis()4615     public int getScanUpgradeDurationMillis() {
4616         synchronized (mDeviceConfigLock) {
4617             return mScanUpgradeDurationMillis;
4618         }
4619     }
4620 
4621     /** Returns scan downgrade duration in millis. */
getScanDowngradeDurationMillis()4622     public int getScanDowngradeDurationMillis() {
4623         synchronized (mDeviceConfigLock) {
4624             return mScanDowngradeDurationMillis;
4625         }
4626     }
4627 
4628     /** Returns SCREEN_OFF_BALANCED scan window in millis. */
getScreenOffBalancedWindowMillis()4629     public int getScreenOffBalancedWindowMillis() {
4630         synchronized (mDeviceConfigLock) {
4631             return mScreenOffBalancedWindowMillis;
4632         }
4633     }
4634 
4635     /** Returns SCREEN_OFF_BALANCED scan interval in millis. */
getScreenOffBalancedIntervalMillis()4636     public int getScreenOffBalancedIntervalMillis() {
4637         synchronized (mDeviceConfigLock) {
4638             return mScreenOffBalancedIntervalMillis;
4639         }
4640     }
4641 
4642     /** Returns SCREEN_OFF low power scan window in millis. */
getScreenOffLowPowerWindowMillis()4643     public int getScreenOffLowPowerWindowMillis() {
4644         synchronized (mDeviceConfigLock) {
4645             return mScreenOffLowPowerWindowMillis;
4646         }
4647     }
4648 
4649     /** Returns SCREEN_OFF low power scan interval in millis. */
getScreenOffLowPowerIntervalMillis()4650     public int getScreenOffLowPowerIntervalMillis() {
4651         synchronized (mDeviceConfigLock) {
4652             return mScreenOffLowPowerIntervalMillis;
4653         }
4654     }
4655 
4656     @VisibleForTesting
4657     public class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener {
4658         private static final String LOCATION_DENYLIST_NAME = "location_denylist_name";
4659         private static final String LOCATION_DENYLIST_MAC = "location_denylist_mac";
4660         private static final String LOCATION_DENYLIST_ADVERTISING_DATA =
4661                 "location_denylist_advertising_data";
4662         private static final String SCAN_QUOTA_COUNT = "scan_quota_count";
4663         private static final String SCAN_QUOTA_WINDOW_MILLIS = "scan_quota_window_millis";
4664         private static final String SCAN_TIMEOUT_MILLIS = "scan_timeout_millis";
4665         private static final String SCAN_UPGRADE_DURATION_MILLIS = "scan_upgrade_duration_millis";
4666         private static final String SCAN_DOWNGRADE_DURATION_MILLIS =
4667                 "scan_downgrade_duration_millis";
4668         private static final String SCREEN_OFF_LOW_POWER_WINDOW_MILLIS =
4669                 "screen_off_low_power_window_millis";
4670         private static final String SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS =
4671                 "screen_off_low_power_interval_millis";
4672         private static final String SCREEN_OFF_BALANCED_WINDOW_MILLIS =
4673                 "screen_off_balanced_window_millis";
4674         private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS =
4675                 "screen_off_balanced_interval_millis";
4676         private static final String LE_AUDIO_ALLOW_LIST = "le_audio_allow_list";
4677 
4678         /**
4679          * Default denylist which matches Eddystone (except for Eddystone-E2EE-EID) and iBeacon
4680          * payloads.
4681          */
4682         private static final String DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA =
4683                 "⊈0016AAFE40/00FFFFFFF0,⊆0016AAFE/00FFFFFF,⊆00FF4C0002/00FFFFFFFF";
4684 
4685         private static final int DEFAULT_SCAN_QUOTA_COUNT = 5;
4686         private static final long DEFAULT_SCAN_QUOTA_WINDOW_MILLIS = 30 * SECOND_IN_MILLIS;
4687 
4688         @VisibleForTesting
4689         public static final long DEFAULT_SCAN_TIMEOUT_MILLIS = 10 * MINUTE_IN_MILLIS;
4690 
4691         @VisibleForTesting
4692         public static final int DEFAULT_SCAN_UPGRADE_DURATION_MILLIS = (int) SECOND_IN_MILLIS * 6;
4693 
4694         @VisibleForTesting
4695         public static final int DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS =
4696                 (int) SECOND_IN_MILLIS * 6;
4697 
start()4698         public void start() {
4699             DeviceConfig.addOnPropertiesChangedListener(
4700                     DeviceConfig.NAMESPACE_BLUETOOTH, BackgroundThread.getExecutor(), this);
4701             onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH));
4702         }
4703 
4704         @Override
onPropertiesChanged(DeviceConfig.Properties properties)4705         public void onPropertiesChanged(DeviceConfig.Properties properties) {
4706             synchronized (mDeviceConfigLock) {
4707                 final String name = properties.getString(LOCATION_DENYLIST_NAME, null);
4708                 mLocationDenylistName =
4709                         !TextUtils.isEmpty(name)
4710                                 ? Pattern.compile(name).asPredicate()
4711                                 : (v) -> false;
4712                 mLocationDenylistMac =
4713                         BytesMatcher.decode(properties.getString(LOCATION_DENYLIST_MAC, null));
4714                 mLocationDenylistAdvertisingData =
4715                         BytesMatcher.decode(
4716                                 properties.getString(
4717                                         LOCATION_DENYLIST_ADVERTISING_DATA,
4718                                         DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA));
4719                 mScanQuotaCount = properties.getInt(SCAN_QUOTA_COUNT, DEFAULT_SCAN_QUOTA_COUNT);
4720                 mScanQuotaWindowMillis =
4721                         properties.getLong(
4722                                 SCAN_QUOTA_WINDOW_MILLIS, DEFAULT_SCAN_QUOTA_WINDOW_MILLIS);
4723                 mScanTimeoutMillis =
4724                         properties.getLong(SCAN_TIMEOUT_MILLIS, DEFAULT_SCAN_TIMEOUT_MILLIS);
4725                 mScanUpgradeDurationMillis =
4726                         properties.getInt(
4727                                 SCAN_UPGRADE_DURATION_MILLIS, DEFAULT_SCAN_UPGRADE_DURATION_MILLIS);
4728                 mScanDowngradeDurationMillis =
4729                         properties.getInt(
4730                                 SCAN_DOWNGRADE_DURATION_MILLIS,
4731                                 DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS);
4732                 mScreenOffLowPowerWindowMillis =
4733                         properties.getInt(
4734                                 SCREEN_OFF_LOW_POWER_WINDOW_MILLIS,
4735                                 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS);
4736                 mScreenOffLowPowerIntervalMillis =
4737                         properties.getInt(
4738                                 SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS,
4739                                 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS);
4740                 mScreenOffBalancedWindowMillis =
4741                         properties.getInt(
4742                                 SCREEN_OFF_BALANCED_WINDOW_MILLIS,
4743                                 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS);
4744                 mScreenOffBalancedIntervalMillis =
4745                         properties.getInt(
4746                                 SCREEN_OFF_BALANCED_INTERVAL_MILLIS,
4747                                 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS);
4748                 mLeAudioAllowList = properties.getString(LE_AUDIO_ALLOW_LIST, "");
4749 
4750                 if (!mLeAudioAllowList.isEmpty()) {
4751                     List<String> leAudioAllowlistFromDeviceConfig =
4752                             Arrays.asList(mLeAudioAllowList.split(","));
4753                     BluetoothProperties.le_audio_allow_list(leAudioAllowlistFromDeviceConfig);
4754                 }
4755 
4756                 List<String> leAudioAllowlistProp = BluetoothProperties.le_audio_allow_list();
4757                 if (leAudioAllowlistProp != null && !leAudioAllowlistProp.isEmpty()) {
4758                     mLeAudioAllowDevices.clear();
4759                     mLeAudioAllowDevices.addAll(leAudioAllowlistProp);
4760                 }
4761             }
4762         }
4763     }
4764 
4765     /** A callback that will be called when AdapterState is changed */
4766     public interface BluetoothStateCallback {
4767         /**
4768          * Called when the status of bluetooth adapter is changing. {@code prevState} and {@code
4769          * newState} takes one of following values defined in BluetoothAdapter.java: STATE_OFF,
4770          * STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON, STATE_BLE_ON,
4771          * STATE_BLE_TURNING_OFF
4772          *
4773          * @param prevState the previous Bluetooth state.
4774          * @param newState the new Bluetooth state.
4775          */
onBluetoothStateChange(int prevState, int newState)4776         void onBluetoothStateChange(int prevState, int newState);
4777     }
4778 
4779     /**
4780      * Obfuscate Bluetooth MAC address into a PII free ID string
4781      *
4782      * @param device Bluetooth device whose MAC address will be obfuscated
4783      * @return a byte array that is unique to this MAC address on this device, or empty byte array
4784      *     when either device is null or obfuscateAddressNative fails
4785      */
obfuscateAddress(BluetoothDevice device)4786     public byte[] obfuscateAddress(BluetoothDevice device) {
4787         if (device == null) {
4788             return new byte[0];
4789         }
4790         return mNativeInterface.obfuscateAddress(Utils.getByteAddress(device));
4791     }
4792 
4793     /**
4794      * Get dynamic audio buffer size supported type
4795      *
4796      * @return support
4797      *     <p>Possible values are {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_NONE}, {@link
4798      *     BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD}, {@link
4799      *     BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}.
4800      */
getDynamicBufferSupport()4801     public int getDynamicBufferSupport() {
4802         return mAdapterProperties.getDynamicBufferSupport();
4803     }
4804 
4805     /**
4806      * Get dynamic audio buffer size
4807      *
4808      * @return BufferConstraints
4809      */
getBufferConstraints()4810     public BufferConstraints getBufferConstraints() {
4811         return mAdapterProperties.getBufferConstraints();
4812     }
4813 
4814     /**
4815      * Set dynamic audio buffer size
4816      *
4817      * @param codec Audio codec
4818      * @param value buffer millis
4819      * @return true if the settings is successful, false otherwise
4820      */
setBufferLengthMillis(int codec, int value)4821     public boolean setBufferLengthMillis(int codec, int value) {
4822         return mAdapterProperties.setBufferLengthMillis(codec, value);
4823     }
4824 
4825     /**
4826      * Get an incremental id of Bluetooth metrics and log
4827      *
4828      * @param device Bluetooth device
4829      * @return int of id for Bluetooth metrics and logging, 0 if the device is invalid
4830      */
getMetricId(BluetoothDevice device)4831     public int getMetricId(BluetoothDevice device) {
4832         if (device == null) {
4833             return 0;
4834         }
4835         return mNativeInterface.getMetricId(Utils.getByteAddress(device));
4836     }
4837 
getCompanionManager()4838     public CompanionManager getCompanionManager() {
4839         return mBtCompanionManager;
4840     }
4841 
4842     /**
4843      * Call for the AdapterService receives bond state change
4844      *
4845      * @param device Bluetooth device
4846      * @param state bond state
4847      */
onBondStateChanged(BluetoothDevice device, int state)4848     public void onBondStateChanged(BluetoothDevice device, int state) {
4849         if (mBtCompanionManager != null) {
4850             mBtCompanionManager.onBondStateChanged(device, state);
4851         }
4852     }
4853 
4854     /**
4855      * Get audio policy feature support status
4856      *
4857      * @param device Bluetooth device to be checked for audio policy support
4858      * @return int status of the remote support for audio policy feature
4859      */
isRequestAudioPolicyAsSinkSupported(BluetoothDevice device)4860     public int isRequestAudioPolicyAsSinkSupported(BluetoothDevice device) {
4861         if (mHeadsetClientService != null) {
4862             return mHeadsetClientService.getAudioPolicyRemoteSupported(device);
4863         } else {
4864             Log.e(TAG, "No audio transport connected");
4865             return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED;
4866         }
4867     }
4868 
4869     /**
4870      * Set audio policy for remote device
4871      *
4872      * @param device Bluetooth device to be set policy for
4873      * @return int result status for requestAudioPolicyAsSink API
4874      */
requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies)4875     public int requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies) {
4876         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4877         if (deviceProp == null) {
4878             return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
4879         }
4880 
4881         if (mHeadsetClientService != null) {
4882             if (isRequestAudioPolicyAsSinkSupported(device)
4883                     != BluetoothStatusCodes.FEATURE_SUPPORTED) {
4884                 throw new UnsupportedOperationException(
4885                         "Request Audio Policy As Sink not supported");
4886             }
4887             deviceProp.setHfAudioPolicyForRemoteAg(policies);
4888             mHeadsetClientService.setAudioPolicy(device, policies);
4889             return BluetoothStatusCodes.SUCCESS;
4890         } else {
4891             Log.e(TAG, "HeadsetClient not connected");
4892             return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
4893         }
4894     }
4895 
4896     /**
4897      * Get audio policy for remote device
4898      *
4899      * @param device Bluetooth device to be set policy for
4900      * @return {@link BluetoothSinkAudioPolicy} policy stored for the device
4901      */
getRequestedAudioPolicyAsSink(BluetoothDevice device)4902     public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(BluetoothDevice device) {
4903         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4904         if (deviceProp == null) {
4905             return null;
4906         }
4907 
4908         if (mHeadsetClientService != null) {
4909             return deviceProp.getHfAudioPolicyForRemoteAg();
4910         } else {
4911             Log.e(TAG, "HeadsetClient not connected");
4912             return null;
4913         }
4914     }
4915 
4916     /**
4917      * Allow audio low latency
4918      *
4919      * @param allowed true if audio low latency is being allowed
4920      * @param device device whose audio low latency will be allowed or disallowed
4921      * @return boolean true if audio low latency is successfully allowed or disallowed
4922      */
allowLowLatencyAudio(boolean allowed, BluetoothDevice device)4923     public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) {
4924         return mNativeInterface.allowLowLatencyAudio(allowed, Utils.getByteAddress(device));
4925     }
4926 
4927     /**
4928      * get remote PBAP PCE version.
4929      *
4930      * @param address of remote device
4931      * @return int value other than 0 if remote PBAP PCE version is found
4932      */
getRemotePbapPceVersion(String address)4933     public int getRemotePbapPceVersion(String address) {
4934         return mNativeInterface.getRemotePbapPceVersion(address);
4935     }
4936 
4937     /**
4938      * check, if PBAP PSE dynamic version upgrade is enabled.
4939      *
4940      * @return true/false.
4941      */
pbapPseDynamicVersionUpgradeIsEnabled()4942     public boolean pbapPseDynamicVersionUpgradeIsEnabled() {
4943         return mNativeInterface.pbapPseDynamicVersionUpgradeIsEnabled();
4944     }
4945 
4946     /** Sets the battery level of the remote device */
setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas)4947     public void setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas) {
4948         if (batteryLevel == BATTERY_LEVEL_UNKNOWN) {
4949             mRemoteDevices.resetBatteryLevel(device, isBas);
4950         } else {
4951             mRemoteDevices.updateBatteryLevel(device, batteryLevel, isBas);
4952         }
4953     }
4954 
interopMatchAddr(InteropFeature feature, String address)4955     public boolean interopMatchAddr(InteropFeature feature, String address) {
4956         return mNativeInterface.interopMatchAddr(feature.name(), address);
4957     }
4958 
interopMatchName(InteropFeature feature, String name)4959     public boolean interopMatchName(InteropFeature feature, String name) {
4960         return mNativeInterface.interopMatchName(feature.name(), name);
4961     }
4962 
interopMatchAddrOrName(InteropFeature feature, String address)4963     public boolean interopMatchAddrOrName(InteropFeature feature, String address) {
4964         return mNativeInterface.interopMatchAddrOrName(feature.name(), address);
4965     }
4966 
interopDatabaseAddAddr(InteropFeature feature, String address, int length)4967     public void interopDatabaseAddAddr(InteropFeature feature, String address, int length) {
4968         mNativeInterface.interopDatabaseAddRemoveAddr(true, feature.name(), address, length);
4969     }
4970 
interopDatabaseRemoveAddr(InteropFeature feature, String address)4971     public void interopDatabaseRemoveAddr(InteropFeature feature, String address) {
4972         mNativeInterface.interopDatabaseAddRemoveAddr(false, feature.name(), address, 0);
4973     }
4974 
interopDatabaseAddName(InteropFeature feature, String name)4975     public void interopDatabaseAddName(InteropFeature feature, String name) {
4976         mNativeInterface.interopDatabaseAddRemoveName(true, feature.name(), name);
4977     }
4978 
interopDatabaseRemoveName(InteropFeature feature, String name)4979     public void interopDatabaseRemoveName(InteropFeature feature, String name) {
4980         mNativeInterface.interopDatabaseAddRemoveName(false, feature.name(), name);
4981     }
4982 
4983     /**
4984      * Checks the remote device is in the LE Audio allow list or not.
4985      *
4986      * @param device the device to check
4987      * @return boolean true if the device is in the allow list, false otherwise.
4988      */
isLeAudioAllowed(BluetoothDevice device)4989     public boolean isLeAudioAllowed(BluetoothDevice device) {
4990         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4991 
4992         if (deviceProp == null
4993                 || deviceProp.getModelName() == null
4994                 || !mLeAudioAllowDevices.contains(deviceProp.getModelName())) {
4995 
4996             return false;
4997         }
4998 
4999         return true;
5000     }
5001 
5002     /**
5003      * Get type of the remote device
5004      *
5005      * @param device the device to check
5006      * @return int device type
5007      */
getRemoteType(BluetoothDevice device)5008     public int getRemoteType(BluetoothDevice device) {
5009         return mRemoteDevices.getType(device);
5010     }
5011 
5012     /**
5013      * Sends service discovery UUIDs internally within the stack. This is meant to remove internal
5014      * dependencies on the broadcast {@link BluetoothDevice#ACTION_UUID}.
5015      *
5016      * @param device is the remote device whose UUIDs have been discovered
5017      * @param uuids are the services supported on the remote device
5018      */
sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids)5019     void sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids) {
5020         if (device == null) {
5021             Log.w(TAG, "sendUuidsInternal: null device");
5022             return;
5023         }
5024         if (uuids == null) {
5025             Log.w(TAG, "sendUuidsInternal: uuids is null");
5026             return;
5027         }
5028         Log.i(TAG, "sendUuidsInternal: Received service discovery UUIDs for device " + device);
5029         for (int i = 0; i < uuids.length; i++) {
5030             Log.d(TAG, "sendUuidsInternal: index=" + i + " uuid=" + uuids[i]);
5031         }
5032         mPhonePolicy.ifPresent(policy -> policy.onUuidsDiscovered(device, uuids));
5033     }
5034 
5035     /** Clear storage */
clearStorage()5036     void clearStorage() {
5037         deleteDirectoryContents("/data/misc/bluedroid/");
5038         deleteDirectoryContents("/data/misc/bluetooth/");
5039     }
5040 
deleteDirectoryContents(String dirPath)5041     private static void deleteDirectoryContents(String dirPath) {
5042         Path directoryPath = Paths.get(dirPath);
5043         try {
5044             Files.walkFileTree(
5045                     directoryPath,
5046                     new SimpleFileVisitor<Path>() {
5047                         @Override
5048                         public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
5049                                 throws IOException {
5050                             Files.delete(file);
5051                             return FileVisitResult.CONTINUE;
5052                         }
5053 
5054                         @Override
5055                         public FileVisitResult postVisitDirectory(Path dir, IOException ex)
5056                                 throws IOException {
5057                             if (ex != null) {
5058                                 Log.e(TAG, "Error happened while removing contents. ", ex);
5059                             }
5060 
5061                             if (!dir.equals(directoryPath)) {
5062                                 try {
5063                                     Files.delete(dir);
5064                                 } catch (Exception e) {
5065                                     Log.e(TAG, "Error happened while removing directory: ", e);
5066                                 }
5067                             }
5068                             return FileVisitResult.CONTINUE;
5069                         }
5070                     });
5071             Log.i(TAG, "deleteDirectoryContents() completed. Path: " + dirPath);
5072         } catch (Exception e) {
5073             Log.e(TAG, "Error happened while removing contents: ", e);
5074         }
5075     }
5076 
5077     /** Get the number of the supported offloaded LE COC sockets. */
getNumberOfSupportedOffloadedLeCocSockets()5078     public int getNumberOfSupportedOffloadedLeCocSockets() {
5079         return mAdapterProperties.getNumberOfSupportedOffloadedLeCocSockets();
5080     }
5081 
5082     /** Check if the offloaded LE COC socket is supported. */
isLeCocSocketOffloadSupported()5083     public boolean isLeCocSocketOffloadSupported() {
5084         int val = getNumberOfSupportedOffloadedLeCocSockets();
5085         return val > 0;
5086     }
5087 
5088     /** Get the number of the supported offloaded RFCOMM sockets. */
getNumberOfSupportedOffloadedRfcommSockets()5089     public int getNumberOfSupportedOffloadedRfcommSockets() {
5090         return mAdapterProperties.getNumberOfSupportedOffloadedRfcommSockets();
5091     }
5092 
5093     /** Check if the offloaded RFCOMM socket is supported. */
isRfcommSocketOffloadSupported()5094     public boolean isRfcommSocketOffloadSupported() {
5095         int val = getNumberOfSupportedOffloadedRfcommSockets();
5096         return val > 0;
5097     }
5098 }
5099