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.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
21 import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO;
22 import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
23 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
24 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
25 
26 import static com.android.bluetooth.ChangeIds.ENFORCE_CONNECT;
27 import static com.android.bluetooth.Utils.callerIsSystem;
28 import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser;
29 import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
30 import static com.android.bluetooth.Utils.enforceCdmAssociation;
31 import static com.android.bluetooth.Utils.enforceDumpPermission;
32 import static com.android.bluetooth.Utils.enforceLocalMacAddressPermission;
33 import static com.android.bluetooth.Utils.getBytesFromAddress;
34 import static com.android.bluetooth.Utils.hasBluetoothPrivilegedPermission;
35 import static com.android.bluetooth.Utils.isDualModeAudioEnabled;
36 import static com.android.bluetooth.Utils.isPackageNameAccurate;
37 
38 import static java.util.Objects.requireNonNull;
39 
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.annotation.RequiresPermission;
43 import android.annotation.SuppressLint;
44 import android.app.AppOpsManager;
45 import android.app.PendingIntent;
46 import android.app.Service;
47 import android.app.admin.DevicePolicyManager;
48 import android.app.compat.CompatChanges;
49 import android.bluetooth.BluetoothA2dp;
50 import android.bluetooth.BluetoothActivityEnergyInfo;
51 import android.bluetooth.BluetoothAdapter;
52 import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile;
53 import android.bluetooth.BluetoothAdapter.ActiveDeviceUse;
54 import android.bluetooth.BluetoothDevice;
55 import android.bluetooth.BluetoothFrameworkInitializer;
56 import android.bluetooth.BluetoothMap;
57 import android.bluetooth.BluetoothProfile;
58 import android.bluetooth.BluetoothProtoEnums;
59 import android.bluetooth.BluetoothQualityReport;
60 import android.bluetooth.BluetoothSap;
61 import android.bluetooth.BluetoothServerSocket;
62 import android.bluetooth.BluetoothSinkAudioPolicy;
63 import android.bluetooth.BluetoothSocket;
64 import android.bluetooth.BluetoothStatusCodes;
65 import android.bluetooth.BluetoothUuid;
66 import android.bluetooth.BufferConstraints;
67 import android.bluetooth.IBluetooth;
68 import android.bluetooth.IBluetoothActivityEnergyInfoListener;
69 import android.bluetooth.IBluetoothCallback;
70 import android.bluetooth.IBluetoothConnectionCallback;
71 import android.bluetooth.IBluetoothMetadataListener;
72 import android.bluetooth.IBluetoothOobDataCallback;
73 import android.bluetooth.IBluetoothPreferredAudioProfilesCallback;
74 import android.bluetooth.IBluetoothQualityReportReadyCallback;
75 import android.bluetooth.IBluetoothSocketManager;
76 import android.bluetooth.IncomingRfcommSocketInfo;
77 import android.bluetooth.OobData;
78 import android.bluetooth.UidTraffic;
79 import android.bluetooth.rfcomm.BluetoothRfcommProtoEnums;
80 import android.companion.CompanionDeviceManager;
81 import android.content.AttributionSource;
82 import android.content.Context;
83 import android.content.Intent;
84 import android.content.SharedPreferences;
85 import android.content.pm.PackageManager;
86 import android.os.AsyncTask;
87 import android.os.BatteryStatsManager;
88 import android.os.Binder;
89 import android.os.Build;
90 import android.os.Bundle;
91 import android.os.Handler;
92 import android.os.IBinder;
93 import android.os.Looper;
94 import android.os.Message;
95 import android.os.ParcelUuid;
96 import android.os.Parcelable;
97 import android.os.PowerManager;
98 import android.os.Process;
99 import android.os.RemoteCallbackList;
100 import android.os.RemoteException;
101 import android.os.SystemClock;
102 import android.os.UserHandle;
103 import android.os.UserManager;
104 import android.provider.DeviceConfig;
105 import android.provider.Settings;
106 import android.sysprop.BluetoothProperties;
107 import android.text.TextUtils;
108 import android.util.Base64;
109 import android.util.Log;
110 import android.util.SparseArray;
111 
112 import com.android.bluetooth.BluetoothMetricsProto;
113 import com.android.bluetooth.BluetoothStatsLog;
114 import com.android.bluetooth.R;
115 import com.android.bluetooth.Utils;
116 import com.android.bluetooth.a2dp.A2dpService;
117 import com.android.bluetooth.a2dpsink.A2dpSinkService;
118 import com.android.bluetooth.avrcp.AvrcpTargetService;
119 import com.android.bluetooth.avrcpcontroller.AvrcpControllerService;
120 import com.android.bluetooth.bas.BatteryService;
121 import com.android.bluetooth.bass_client.BassClientService;
122 import com.android.bluetooth.btservice.InteropUtil.InteropFeature;
123 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
124 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreNativeInterface;
125 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService;
126 import com.android.bluetooth.btservice.storage.DatabaseManager;
127 import com.android.bluetooth.btservice.storage.MetadataDatabase;
128 import com.android.bluetooth.csip.CsipSetCoordinatorService;
129 import com.android.bluetooth.flags.Flags;
130 import com.android.bluetooth.gatt.GattService;
131 import com.android.bluetooth.hap.HapClientService;
132 import com.android.bluetooth.hearingaid.HearingAidService;
133 import com.android.bluetooth.hfp.HeadsetService;
134 import com.android.bluetooth.hfpclient.HeadsetClientService;
135 import com.android.bluetooth.hid.HidDeviceService;
136 import com.android.bluetooth.hid.HidHostService;
137 import com.android.bluetooth.le_audio.LeAudioService;
138 import com.android.bluetooth.le_scan.ScanController;
139 import com.android.bluetooth.le_scan.ScanManager;
140 import com.android.bluetooth.map.BluetoothMapService;
141 import com.android.bluetooth.mapclient.MapClientService;
142 import com.android.bluetooth.mcp.McpService;
143 import com.android.bluetooth.opp.BluetoothOppService;
144 import com.android.bluetooth.pan.PanService;
145 import com.android.bluetooth.pbap.BluetoothPbapService;
146 import com.android.bluetooth.pbapclient.PbapClientService;
147 import com.android.bluetooth.sap.SapService;
148 import com.android.bluetooth.sdp.SdpManager;
149 import com.android.bluetooth.tbs.TbsService;
150 import com.android.bluetooth.telephony.BluetoothInCallService;
151 import com.android.bluetooth.vc.VolumeControlService;
152 import com.android.internal.annotations.GuardedBy;
153 import com.android.internal.annotations.VisibleForTesting;
154 import com.android.modules.expresslog.Counter;
155 import com.android.modules.utils.BackgroundThread;
156 import com.android.modules.utils.BytesMatcher;
157 
158 import libcore.util.SneakyThrow;
159 
160 import com.google.protobuf.InvalidProtocolBufferException;
161 
162 import java.io.FileDescriptor;
163 import java.io.FileOutputStream;
164 import java.io.IOException;
165 import java.io.PrintWriter;
166 import java.time.Duration;
167 import java.util.ArrayDeque;
168 import java.util.ArrayList;
169 import java.util.Arrays;
170 import java.util.Collections;
171 import java.util.HashMap;
172 import java.util.HashSet;
173 import java.util.Iterator;
174 import java.util.List;
175 import java.util.Map;
176 import java.util.Set;
177 import java.util.UUID;
178 import java.util.concurrent.ConcurrentHashMap;
179 import java.util.concurrent.ConcurrentLinkedQueue;
180 import java.util.concurrent.Executor;
181 import java.util.function.Function;
182 import java.util.function.Predicate;
183 import java.util.regex.Pattern;
184 import java.util.stream.Collectors;
185 
186 public class AdapterService extends Service {
187     private static final String TAG = "BluetoothAdapterService";
188 
189     private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1;
190     private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
191     private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;
192     private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4;
193 
194     private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 100;
195     private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
196     private static final int MIN_OFFLOADED_FILTERS = 10;
197     private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024;
198 
199     private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1);
200     private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2);
201     private static final Duration PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT = Duration.ofSeconds(10);
202 
203     static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission";
204     static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = "message_access_permission";
205     static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission";
206 
207     private static BluetoothProperties.snoop_log_mode_values sSnoopLogSettingAtEnable =
208             BluetoothProperties.snoop_log_mode_values.EMPTY;
209     private static String sDefaultSnoopLogSettingAtEnable = "empty";
210     private static boolean sSnoopLogFilterHeadersSettingAtEnable = false;
211     private static boolean sSnoopLogFilterProfileA2dpSettingAtEnable = false;
212     private static boolean sSnoopLogFilterProfileRfcommSettingAtEnable = false;
213 
214     private static BluetoothProperties.snoop_log_filter_profile_pbap_values
215             sSnoopLogFilterProfilePbapModeSettingAtEnable =
216                     BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY;
217     private static BluetoothProperties.snoop_log_filter_profile_map_values
218             sSnoopLogFilterProfileMapModeSettingAtEnable =
219                     BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY;
220 
221     private static AdapterService sAdapterService;
222 
223     private final Object mEnergyInfoLock = new Object();
224     private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>();
225 
226     private final Map<Integer, ProfileService> mStartedProfiles = new HashMap<>();
227     private final List<ProfileService> mRegisteredProfiles = new ArrayList<>();
228     private final List<ProfileService> mRunningProfiles = new ArrayList<>();
229 
230     private final List<DiscoveringPackage> mDiscoveringPackages = new ArrayList<>();
231 
232     private final AdapterNativeInterface mNativeInterface = AdapterNativeInterface.getInstance();
233 
234     private final Map<BluetoothDevice, List<IBluetoothMetadataListener>> mMetadataListeners =
235             new HashMap<>();
236 
237     // Map<groupId, PendingAudioProfilePreferenceRequest>
238     @GuardedBy("mCsipGroupsPendingAudioProfileChanges")
239     private final Map<Integer, PendingAudioProfilePreferenceRequest>
240             mCsipGroupsPendingAudioProfileChanges = new HashMap<>();
241 
242     private final Map<BluetoothStateCallback, Executor> mLocalCallbacks = new ConcurrentHashMap<>();
243     private final Map<UUID, RfcommListenerData> mBluetoothServerSockets = new ConcurrentHashMap<>();
244     private final ArrayDeque<IBluetoothOobDataCallback> mOobDataCallbackQueue = new ArrayDeque<>();
245 
246     private final RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback>
247             mPreferredAudioProfilesCallbacks = new RemoteCallbackList<>();
248     private final RemoteCallbackList<IBluetoothQualityReportReadyCallback>
249             mBluetoothQualityReportReadyCallbacks = new RemoteCallbackList<>();
250     private final RemoteCallbackList<IBluetoothCallback> mRemoteCallbacks =
251             new RemoteCallbackList<>();
252 
253     private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener();
254 
255     private final Looper mLooper;
256     private final AdapterServiceHandler mHandler;
257 
258     private int mStackReportedState;
259     private long mTxTimeTotalMs;
260     private long mRxTimeTotalMs;
261     private long mIdleTimeTotalMs;
262     private long mEnergyUsedTotalVoltAmpSecMicro;
263     private HashSet<String> mLeAudioAllowDevices = new HashSet<>();
264 
265     private BluetoothAdapter mAdapter;
266     @VisibleForTesting AdapterProperties mAdapterProperties;
267     private AdapterState mAdapterStateMachine;
268     private BondStateMachine mBondStateMachine;
269     private RemoteDevices mRemoteDevices;
270 
271     /* TODO: Consider to remove the search API from this class, if changed to use call-back */
272     private SdpManager mSdpManager = null;
273 
274     private boolean mNativeAvailable;
275     private boolean mCleaningUp;
276     private Set<IBluetoothConnectionCallback> mBluetoothConnectionCallbacks = new HashSet<>();
277     private boolean mQuietmode = false;
278     private Map<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>();
279 
280     private BatteryStatsManager mBatteryStatsManager;
281     private PowerManager mPowerManager;
282     private PowerManager.WakeLock mWakeLock;
283     private UserManager mUserManager;
284     private CompanionDeviceManager mCompanionDeviceManager;
285 
286     // Phone Policy is not used on all devices. Ensure you null check before using it
287     @Nullable private PhonePolicy mPhonePolicy;
288 
289     private ActiveDeviceManager mActiveDeviceManager;
290     private final DatabaseManager mDatabaseManager;
291     private final SilenceDeviceManager mSilenceDeviceManager;
292     private CompanionManager mBtCompanionManager;
293     private AppOpsManager mAppOps;
294 
295     private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder;
296 
297     private BluetoothKeystoreService mBluetoothKeystoreService;
298     private A2dpService mA2dpService;
299     private A2dpSinkService mA2dpSinkService;
300     private HeadsetService mHeadsetService;
301     private HeadsetClientService mHeadsetClientService;
302     private BluetoothMapService mMapService;
303     private MapClientService mMapClientService;
304     private HidDeviceService mHidDeviceService;
305     private HidHostService mHidHostService;
306     private PanService mPanService;
307     private BluetoothPbapService mPbapService;
308     private PbapClientService mPbapClientService;
309     private HearingAidService mHearingAidService;
310     private HapClientService mHapClientService;
311     private SapService mSapService;
312     private VolumeControlService mVolumeControlService;
313     private CsipSetCoordinatorService mCsipSetCoordinatorService;
314     private LeAudioService mLeAudioService;
315     private BassClientService mBassClientService;
316     private BatteryService mBatteryService;
317     private BluetoothQualityReportNativeInterface mBluetoothQualityReportNativeInterface;
318     private GattService mGattService;
319     private ScanController mScanController;
320 
321     private volatile boolean mTestModeEnabled = false;
322 
323     private MetricsLogger mMetricsLogger;
324 
325     /** Handlers for incoming service calls */
326     private AdapterServiceBinder mBinder;
327 
328     // Report ID definition
329     public enum BqrQualityReportId {
330         QUALITY_REPORT_ID_MONITOR_MODE(0x01),
331         QUALITY_REPORT_ID_APPROACH_LSTO(0x02),
332         QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY(0x03),
333         QUALITY_REPORT_ID_SCO_VOICE_CHOPPY(0x04),
334         QUALITY_REPORT_ID_ROOT_INFLAMMATION(0x05),
335         QUALITY_REPORT_ID_CONNECT_FAIL(0x08),
336         QUALITY_REPORT_ID_LMP_LL_MESSAGE_TRACE(0x11),
337         QUALITY_REPORT_ID_BT_SCHEDULING_TRACE(0x12),
338         QUALITY_REPORT_ID_CONTROLLER_DBG_INFO(0x13);
339 
340         private final int mValue;
341 
BqrQualityReportId(int value)342         BqrQualityReportId(int value) {
343             mValue = value;
344         }
345 
getValue()346         public int getValue() {
347             return mValue;
348         }
349     };
350 
351     static {
352         if (!Flags.avoidStaticLoadingOfNative()) {
Log.d(TAG, "Loading JNI Library")353             Log.d(TAG, "Loading JNI Library");
354             if (Utils.isInstrumentationTestMode()) {
Log.w(TAG, "App is instrumented. Skip loading the native")355                 Log.w(TAG, "App is instrumented. Skip loading the native");
356             } else {
357                 System.loadLibrary("bluetooth_jni");
358             }
359         }
360     }
361 
362     // Keep a constructor for ActivityThread.handleCreateService
AdapterService()363     AdapterService() {
364         this(Looper.getMainLooper());
365     }
366 
367     @VisibleForTesting
AdapterService(Looper looper)368     AdapterService(Looper looper) {
369         mLooper = requireNonNull(looper);
370         mHandler = new AdapterServiceHandler(mLooper);
371         mSilenceDeviceManager = new SilenceDeviceManager(this, new ServiceFactory(), mLooper);
372         mDatabaseManager = new DatabaseManager(this);
373     }
374 
375     @VisibleForTesting
AdapterService(Context ctx)376     public AdapterService(Context ctx) {
377         this(Looper.getMainLooper());
378         attachBaseContext(ctx);
379     }
380 
getAdapterService()381     public static synchronized AdapterService getAdapterService() {
382         return sAdapterService;
383     }
384 
getNative()385     AdapterNativeInterface getNative() {
386         return mNativeInterface;
387     }
388 
389     /** Allow test to set an AdapterService to be return by AdapterService.getAdapterService() */
390     @VisibleForTesting
setAdapterService(AdapterService instance)391     public static synchronized void setAdapterService(AdapterService instance) {
392         if (instance == null) {
393             Log.e(TAG, "setAdapterService() - instance is null");
394             return;
395         }
396         Log.d(TAG, "setAdapterService() - set service to " + instance);
397         sAdapterService = instance;
398     }
399 
400     /** Clear test Adapter service. See {@code setAdapterService} */
401     @VisibleForTesting
clearAdapterService(AdapterService instance)402     public static synchronized void clearAdapterService(AdapterService instance) {
403         if (sAdapterService == instance) {
404             Log.d(TAG, "clearAdapterService() - This adapter was cleared " + instance);
405             sAdapterService = null;
406         } else {
407             Log.d(
408                     TAG,
409                     "clearAdapterService() - incorrect cleared adapter."
410                             + (" Instance=" + instance)
411                             + (" vs sAdapterService=" + sAdapterService));
412         }
413     }
414 
415     /**
416      * Register a {@link ProfileService} with AdapterService.
417      *
418      * @param profile the service being added.
419      */
addProfile(ProfileService profile)420     public void addProfile(ProfileService profile) {
421         mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget();
422     }
423 
424     /**
425      * Unregister a ProfileService with AdapterService.
426      *
427      * @param profile the service being removed.
428      */
removeProfile(ProfileService profile)429     public void removeProfile(ProfileService profile) {
430         mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget();
431     }
432 
433     /**
434      * Notify AdapterService that a ProfileService has started or stopped.
435      *
436      * @param profile the service being removed.
437      * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF}
438      */
onProfileServiceStateChanged(ProfileService profile, int state)439     public void onProfileServiceStateChanged(ProfileService profile, int state) {
440         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
441             throw new IllegalArgumentException(BluetoothAdapter.nameForState(state));
442         }
443         Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
444         m.obj = profile;
445         m.arg1 = state;
446         mHandler.sendMessage(m);
447     }
448 
449     class AdapterServiceHandler extends Handler {
AdapterServiceHandler(Looper looper)450         AdapterServiceHandler(Looper looper) {
451             super(looper);
452         }
453 
454         @Override
handleMessage(Message msg)455         public void handleMessage(Message msg) {
456             Log.v(TAG, "handleMessage() - Message: " + msg.what);
457 
458             switch (msg.what) {
459                 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:
460                     Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
461                     processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);
462                     break;
463                 case MESSAGE_PROFILE_SERVICE_REGISTERED:
464                     Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED");
465                     registerProfileService((ProfileService) msg.obj);
466                     break;
467                 case MESSAGE_PROFILE_SERVICE_UNREGISTERED:
468                     Log.v(TAG, "handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
469                     unregisterProfileService((ProfileService) msg.obj);
470                     break;
471                 case MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT:
472                     Log.e(
473                             TAG,
474                             "handleMessage() - "
475                                     + "MESSAGE_PREFERRED_PROFILE_CHANGE_AUDIO_FRAMEWORK_TIMEOUT");
476                     int groupId = (int) msg.obj;
477 
478                     synchronized (mCsipGroupsPendingAudioProfileChanges) {
479                         removeFromPendingAudioProfileChanges(groupId);
480                         PendingAudioProfilePreferenceRequest request =
481                                 mCsipGroupsPendingAudioProfileChanges.remove(groupId);
482                         Log.e(
483                                 TAG,
484                                 "Preferred audio profiles change audio framework timeout for "
485                                         + ("device " + request.mDeviceRequested));
486                         sendPreferredAudioProfilesCallbackToApps(
487                                 request.mDeviceRequested,
488                                 request.mRequestedPreferences,
489                                 BluetoothStatusCodes.ERROR_TIMEOUT);
490                     }
491                     break;
492             }
493         }
494 
registerProfileService(ProfileService profile)495         private void registerProfileService(ProfileService profile) {
496             if (mRegisteredProfiles.contains(profile)) {
497                 Log.e(TAG, profile.getName() + " already registered.");
498                 return;
499             }
500             mRegisteredProfiles.add(profile);
501         }
502 
unregisterProfileService(ProfileService profile)503         private void unregisterProfileService(ProfileService profile) {
504             if (!mRegisteredProfiles.contains(profile)) {
505                 Log.e(TAG, profile.getName() + " not registered (UNREGISTER).");
506                 return;
507             }
508             mRegisteredProfiles.remove(profile);
509         }
510 
processProfileServiceStateChanged(ProfileService profile, int state)511         private void processProfileServiceStateChanged(ProfileService profile, int state) {
512             switch (state) {
513                 case BluetoothAdapter.STATE_ON:
514                     if (!mRegisteredProfiles.contains(profile)) {
515                         Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
516                         return;
517                     }
518                     if (mRunningProfiles.contains(profile)) {
519                         Log.e(TAG, profile.getName() + " already running.");
520                         return;
521                     }
522                     mRunningProfiles.add(profile);
523                     // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware
524                     // initialization. Configuring a device without GATT causes start up failures.
525                     if (GattService.class.getSimpleName().equals(profile.getName())
526                             && !Flags.scanManagerRefactor()) {
527                         mNativeInterface.enable();
528                     } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
529                             && mRegisteredProfiles.size() == mRunningProfiles.size()) {
530                         mAdapterProperties.onBluetoothReady();
531                         updateUuids();
532                         initProfileServices();
533                         mNativeInterface.getAdapterProperty(
534                                 AbstractionLayer.BT_PROPERTY_DYNAMIC_AUDIO_BUFFER);
535                         mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
536                         mBtCompanionManager.loadCompanionInfo();
537                     }
538                     break;
539                 case BluetoothAdapter.STATE_OFF:
540                     if (!mRegisteredProfiles.contains(profile)) {
541                         Log.e(TAG, profile.getName() + " not registered (STATE_OFF).");
542                         return;
543                     }
544                     if (!mRunningProfiles.contains(profile)) {
545                         Log.e(TAG, profile.getName() + " not running.");
546                         return;
547                     }
548                     mRunningProfiles.remove(profile);
549 
550                     if (Flags.scanManagerRefactor()) {
551                         if (mRunningProfiles.size() == 0) {
552                             mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
553                         }
554                     } else {
555                         // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the
556                         // only profile available in the "BLE ON" state. If only GATT is left, send
557                         // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware.
558                         if ((mRunningProfiles.size() == 1
559                                 && (GattService.class
560                                         .getSimpleName()
561                                         .equals(mRunningProfiles.get(0).getName())))) {
562                             mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
563                         } else if (mRunningProfiles.size() == 0) {
564                             mNativeInterface.disable();
565                         }
566                     }
567                     break;
568                 default:
569                     Log.e(TAG, "Unhandled profile state: " + state);
570             }
571         }
572     }
573 
574     /**
575      * Stores information about requests made to the audio framework arising from calls to {@link
576      * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)}.
577      */
578     private static class PendingAudioProfilePreferenceRequest {
579         // The newly requested preferences
580         final Bundle mRequestedPreferences;
581         // Reference counter for how many calls are pending completion in the audio framework
582         int mRemainingRequestsToAudioFramework;
583         // The device with which the request was made. Used for sending the callback.
584         final BluetoothDevice mDeviceRequested;
585 
586         /**
587          * Constructs an entity to store information about pending preferred audio profile changes.
588          *
589          * @param preferences newly requested preferences
590          * @param numRequestsToAudioFramework how many active device changed requests are sent to
591          *     the audio framework
592          * @param device the device with which the request was made
593          */
PendingAudioProfilePreferenceRequest( Bundle preferences, int numRequestsToAudioFramework, BluetoothDevice device)594         PendingAudioProfilePreferenceRequest(
595                 Bundle preferences, int numRequestsToAudioFramework, BluetoothDevice device) {
596             mRequestedPreferences = preferences;
597             mRemainingRequestsToAudioFramework = numRequestsToAudioFramework;
598             mDeviceRequested = device;
599         }
600     }
601 
getNonNullSystemService(@onNull Class<T> clazz)602     final @NonNull <T> T getNonNullSystemService(@NonNull Class<T> clazz) {
603         return requireNonNull(getSystemService(clazz), clazz.getSimpleName() + " cannot be null");
604     }
605 
606     @Override
607     @RequiresPermission(
608             allOf = {
609                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
610                 android.Manifest.permission.READ_DEVICE_CONFIG,
611             },
612             anyOf = {
613                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
614                 android.Manifest.permission.INTERACT_ACROSS_USERS,
615                 android.Manifest.permission.CREATE_USERS,
616                 android.Manifest.permission.MANAGE_USERS,
617             })
onCreate()618     public void onCreate() {
619         super.onCreate();
620         Log.d(TAG, "onCreate()");
621         if (!Flags.fastBindToApp()) {
622             init();
623             return;
624         }
625         // OnCreate must perform the minimum of infaillible and mandatory initialization
626         mRemoteDevices = new RemoteDevices(this, mLooper);
627         mAdapterProperties = new AdapterProperties(this);
628         mAdapterStateMachine = new AdapterState(this, mLooper);
629         mBinder = new AdapterServiceBinder(this);
630         mUserManager = getNonNullSystemService(UserManager.class);
631         mAppOps = getNonNullSystemService(AppOpsManager.class);
632         mPowerManager = getNonNullSystemService(PowerManager.class);
633         mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class);
634         mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class);
635         setAdapterService(this);
636     }
637 
init()638     private void init() {
639         Log.d(TAG, "init()");
640         Config.init(this);
641         initMetricsLogger();
642         mDeviceConfigListener.start();
643 
644         if (!Flags.fastBindToApp()) {
645             // Moved to OnCreate
646             mUserManager = getNonNullSystemService(UserManager.class);
647             mAppOps = getNonNullSystemService(AppOpsManager.class);
648             mPowerManager = getNonNullSystemService(PowerManager.class);
649             mBatteryStatsManager = getNonNullSystemService(BatteryStatsManager.class);
650             mCompanionDeviceManager = getNonNullSystemService(CompanionDeviceManager.class);
651             mRemoteDevices = new RemoteDevices(this, mLooper);
652         }
653 
654         clearDiscoveringPackages();
655         if (!Flags.fastBindToApp()) {
656             mBinder = new AdapterServiceBinder(this);
657         }
658         mAdapter = BluetoothAdapter.getDefaultAdapter();
659         if (!Flags.fastBindToApp()) {
660             // Moved to OnCreate
661             mAdapterProperties = new AdapterProperties(this);
662             mAdapterStateMachine = new AdapterState(this, mLooper);
663         }
664         boolean isCommonCriteriaMode =
665                 getNonNullSystemService(DevicePolicyManager.class)
666                         .isCommonCriteriaModeEnabled(null);
667         mBluetoothKeystoreService =
668                 new BluetoothKeystoreService(
669                         BluetoothKeystoreNativeInterface.getInstance(), isCommonCriteriaMode);
670         mBluetoothKeystoreService.start();
671         int configCompareResult = mBluetoothKeystoreService.getCompareResult();
672 
673         // Start tracking Binder latency for the bluetooth process.
674         BluetoothFrameworkInitializer.initializeBinderCallsStats(getApplicationContext());
675 
676         // Android TV doesn't show consent dialogs for just works and encryption only le pairing
677         boolean isAtvDevice =
678                 getApplicationContext()
679                         .getPackageManager()
680                         .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
681         if (Flags.avoidStaticLoadingOfNative()) {
682             if (Utils.isInstrumentationTestMode()) {
683                 Log.w(TAG, "This Bluetooth App is instrumented. ** Skip loading the native **");
684             } else {
685                 Log.d(TAG, "Loading JNI Library");
686                 System.loadLibrary("bluetooth_jni");
687             }
688         }
689         mNativeInterface.init(
690                 this,
691                 mAdapterProperties,
692                 mUserManager.isGuestUser(),
693                 isCommonCriteriaMode,
694                 configCompareResult,
695                 getInitFlags(),
696                 isAtvDevice,
697                 getApplicationInfo().dataDir);
698         mNativeAvailable = true;
699         // Load the name and address
700         mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDADDR);
701         mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_BDNAME);
702         mNativeInterface.getAdapterProperty(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE);
703 
704         mBluetoothKeystoreService.initJni();
705 
706         mBluetoothQualityReportNativeInterface =
707                 requireNonNull(
708                         BluetoothQualityReportNativeInterface.getInstance(),
709                         "BluetoothQualityReportNativeInterface cannot be null when BQR starts");
710         mBluetoothQualityReportNativeInterface.init();
711 
712         if (Flags.fastBindToApp()) {
713             mSdpManager = new SdpManager(this, mLooper);
714         } else {
715             mSdpManager = new SdpManager(this);
716         }
717 
718         mDatabaseManager.start(MetadataDatabase.createDatabase(this));
719 
720         boolean isAutomotiveDevice =
721                 getApplicationContext()
722                         .getPackageManager()
723                         .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
724 
725         /*
726          * Phone policy is specific to phone implementations and hence if a device wants to exclude
727          * it out then it can be disabled by using the flag below. Phone policy is never used on
728          * Android Automotive OS builds, in favor of a policy currently located in
729          * CarBluetoothService.
730          */
731         if (!isAutomotiveDevice && getResources().getBoolean(R.bool.enable_phone_policy)) {
732             Log.i(TAG, "Phone policy enabled");
733             mPhonePolicy = new PhonePolicy(this, new ServiceFactory());
734             mPhonePolicy.start();
735         } else {
736             Log.i(TAG, "Phone policy disabled");
737         }
738 
739         if (Flags.audioRoutingCentralization()) {
740             mActiveDeviceManager = new AudioRoutingManager(this, new ServiceFactory());
741         } else {
742             mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory());
743         }
744         mActiveDeviceManager.start();
745 
746         mSilenceDeviceManager.start();
747 
748         mBtCompanionManager = new CompanionManager(this, new ServiceFactory());
749 
750         mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this);
751 
752         if (!Flags.fastBindToApp()) {
753             setAdapterService(this);
754         }
755 
756         invalidateBluetoothCaches();
757 
758         // First call to getSharedPreferences will result in a file read into
759         // memory cache. Call it here asynchronously to avoid potential ANR
760         // in the future
761         new AsyncTask<Void, Void, Void>() {
762             @Override
763             protected Void doInBackground(Void... params) {
764                 getSharedPreferences(
765                         PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
766                 getSharedPreferences(
767                         MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
768                 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
769                 return null;
770             }
771         }.execute();
772 
773         try {
774             int systemUiUid =
775                     getApplicationContext()
776                             .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0)
777                             .getPackageManager()
778                             .getPackageUid(
779                                     "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY);
780 
781             Utils.setSystemUiUid(systemUiUid);
782         } catch (PackageManager.NameNotFoundException e) {
783             // Some platforms, such as wearables do not have a system ui.
784             Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
785         }
786     }
787 
788     @Override
onBind(Intent intent)789     public IBinder onBind(Intent intent) {
790         Log.d(TAG, "onBind()");
791         return mBinder;
792     }
793 
794     @Override
795     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
onUnbind(Intent intent)796     public boolean onUnbind(Intent intent) {
797         if (Flags.explicitKillFromSystemServer()) {
798             Log.d(TAG, "onUnbind()");
799             return super.onUnbind(intent);
800         }
801         Log.d(TAG, "onUnbind() - calling cleanup");
802         cleanup();
803         return super.onUnbind(intent);
804     }
805 
806     @Override
onDestroy()807     public void onDestroy() {
808         Log.d(TAG, "onDestroy()");
809         if (Flags.explicitKillFromSystemServer()) {
810             return;
811         }
812         if (!isMock()) {
813             // TODO(b/27859763)
814             Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack");
815             System.exit(0);
816         }
817     }
818 
getActiveDeviceManager()819     public ActiveDeviceManager getActiveDeviceManager() {
820         return mActiveDeviceManager;
821     }
822 
getSilenceDeviceManager()823     public SilenceDeviceManager getSilenceDeviceManager() {
824         return mSilenceDeviceManager;
825     }
826 
initMetricsLogger()827     private boolean initMetricsLogger() {
828         if (mMetricsLogger != null) {
829             return false;
830         }
831         mMetricsLogger = MetricsLogger.getInstance();
832         return mMetricsLogger.init(this);
833     }
834 
closeMetricsLogger()835     private boolean closeMetricsLogger() {
836         if (mMetricsLogger == null) {
837             return false;
838         }
839         boolean result = mMetricsLogger.close();
840         mMetricsLogger = null;
841         return result;
842     }
843 
844     /**
845      * Log L2CAP CoC Server Connection Metrics
846      *
847      * @param port port of socket
848      * @param isSecured if secured API is called
849      * @param result transaction result of the connection
850      * @param socketCreationLatencyMillis latency of the connection
851      * @param timeoutMillis timeout set by the app
852      */
logL2capcocServerConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis, long timeoutMillis, int appUid)853     public void logL2capcocServerConnection(
854             BluetoothDevice device,
855             int port,
856             boolean isSecured,
857             int result,
858             long socketCreationTimeMillis,
859             long socketCreationLatencyMillis,
860             long socketConnectionTimeMillis,
861             long timeoutMillis,
862             int appUid) {
863 
864         int metricId = 0;
865         if (device != null) {
866             metricId = getMetricId(device);
867         }
868         long currentTime = System.currentTimeMillis();
869         long endToEndLatencyMillis = currentTime - socketCreationTimeMillis;
870         long socketAcceptanceLatencyMillis = currentTime - socketConnectionTimeMillis;
871         Log.i(
872                 TAG,
873                 "Statslog L2capcoc server connection."
874                         + (" metricId " + metricId)
875                         + (" port " + port)
876                         + (" isSecured " + isSecured)
877                         + (" result " + result)
878                         + (" endToEndLatencyMillis " + endToEndLatencyMillis)
879                         + (" socketCreationLatencyMillis " + socketCreationLatencyMillis)
880                         + (" socketAcceptanceLatencyMillis " + socketAcceptanceLatencyMillis)
881                         + (" timeout set by app " + timeoutMillis)
882                         + (" appUid " + appUid));
883         BluetoothStatsLog.write(
884                 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_SERVER_CONNECTION,
885                 metricId,
886                 port,
887                 isSecured,
888                 result,
889                 endToEndLatencyMillis,
890                 timeoutMillis,
891                 appUid,
892                 socketCreationLatencyMillis,
893                 socketAcceptanceLatencyMillis);
894     }
895 
setMetricsLogger(MetricsLogger metricsLogger)896     public void setMetricsLogger(MetricsLogger metricsLogger) {
897         mMetricsLogger = metricsLogger;
898     }
899 
900     /**
901      * Log L2CAP CoC Client Connection Metrics
902      *
903      * @param device Bluetooth device
904      * @param port port of socket
905      * @param isSecured if secured API is called
906      * @param result transaction result of the connection
907      * @param socketCreationLatencyNanos latency of the connection
908      */
logL2capcocClientConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeNanos, long socketCreationLatencyNanos, long socketConnectionTimeNanos, int appUid)909     public void logL2capcocClientConnection(
910             BluetoothDevice device,
911             int port,
912             boolean isSecured,
913             int result,
914             long socketCreationTimeNanos,
915             long socketCreationLatencyNanos,
916             long socketConnectionTimeNanos,
917             int appUid) {
918 
919         int metricId = getMetricId(device);
920         long currentTime = System.nanoTime();
921         long endToEndLatencyMillis = (currentTime - socketCreationTimeNanos) / 1000000;
922         long socketCreationLatencyMillis = socketCreationLatencyNanos / 1000000;
923         long socketConnectionLatencyMillis = (currentTime - socketConnectionTimeNanos) / 1000000;
924         Log.i(
925                 TAG,
926                 "Statslog L2capcoc client connection."
927                         + (" metricId " + metricId)
928                         + (" port " + port)
929                         + (" isSecured " + isSecured)
930                         + (" result " + result)
931                         + (" endToEndLatencyMillis " + endToEndLatencyMillis)
932                         + (" socketCreationLatencyMillis " + socketCreationLatencyMillis)
933                         + (" socketConnectionLatencyMillis " + socketConnectionLatencyMillis)
934                         + (" appUid " + appUid));
935         BluetoothStatsLog.write(
936                 BluetoothStatsLog.BLUETOOTH_L2CAP_COC_CLIENT_CONNECTION,
937                 metricId,
938                 port,
939                 isSecured,
940                 result,
941                 endToEndLatencyMillis,
942                 appUid,
943                 socketCreationLatencyMillis,
944                 socketConnectionLatencyMillis);
945     }
946 
947     /**
948      * Log RFCOMM Connection Metrics
949      *
950      * @param device Bluetooth device
951      * @param isSecured if secured API is called
952      * @param resultCode transaction result of the connection
953      * @param isSerialPort true if service class UUID is 0x1101
954      */
logRfcommConnectionAttempt( BluetoothDevice device, boolean isSecured, int resultCode, long socketCreationTimeNanos, boolean isSerialPort, int appUid)955     public void logRfcommConnectionAttempt(
956             BluetoothDevice device,
957             boolean isSecured,
958             int resultCode,
959             long socketCreationTimeNanos,
960             boolean isSerialPort,
961             int appUid) {
962         int metricId = getMetricId(device);
963         long currentTime = System.nanoTime();
964         long endToEndLatencyNanos = currentTime - socketCreationTimeNanos;
965         byte[] remoteDeviceInfoBytes = MetricsLogger.getInstance().getRemoteDeviceInfoProto(device);
966         BluetoothStatsLog.write(
967                 BluetoothStatsLog.BLUETOOTH_RFCOMM_CONNECTION_ATTEMPTED,
968                 metricId,
969                 endToEndLatencyNanos,
970                 isSecured
971                         ? BluetoothRfcommProtoEnums.SOCKET_SECURITY_SECURE
972                         : BluetoothRfcommProtoEnums.SOCKET_SECURITY_INSECURE,
973                 resultCode,
974                 isSerialPort,
975                 appUid,
976                 remoteDeviceInfoBytes);
977     }
978 
979     @RequiresPermission(
980             allOf = {
981                 android.Manifest.permission.BLUETOOTH_CONNECT,
982                 android.Manifest.permission.UPDATE_DEVICE_STATS,
983             })
bringUpBle()984     void bringUpBle() {
985         Log.d(TAG, "bleOnProcessStart()");
986 
987         if (getResources()
988                 .getBoolean(R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
989             Config.init(getApplicationContext());
990         }
991 
992         // Reset |mRemoteDevices| whenever BLE is turned off then on
993         // This is to replace the fact that |mRemoteDevices| was
994         // reinitialized in previous code.
995         //
996         // TODO(apanicke): The reason is unclear but
997         // I believe it is to clear the variable every time BLE was
998         // turned off then on. The same effect can be achieved by
999         // calling cleanup but this may not be necessary at all
1000         // We should figure out why this is needed later
1001         mRemoteDevices.reset();
1002         mAdapterProperties.init(mRemoteDevices);
1003 
1004         Log.d(TAG, "bleOnProcessStart() - Make Bond State Machine");
1005         mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);
1006 
1007         mNativeInterface.getCallbacks().init(mBondStateMachine, mRemoteDevices);
1008 
1009         mBatteryStatsManager.reportBleScanReset();
1010         BluetoothStatsLog.write_non_chained(
1011                 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED,
1012                 -1,
1013                 null,
1014                 BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET,
1015                 false,
1016                 false,
1017                 false);
1018 
1019         // TODO(b/228875190): GATT is assumed supported. As a result, we don't respect the
1020         // configuration sysprop. Configuring a device without GATT, although rare, will cause stack
1021         // start up errors yielding init loops.
1022         if (!GattService.isEnabled()) {
1023             Log.w(
1024                     TAG,
1025                     "GATT is configured off but the stack assumes it to be enabled. Start anyway.");
1026         }
1027         if (Flags.scanManagerRefactor()) {
1028             startScanController();
1029         } else {
1030             startGattProfileService();
1031         }
1032     }
1033 
bringDownBle()1034     void bringDownBle() {
1035         if (Flags.scanManagerRefactor()) {
1036             stopScanController();
1037         } else {
1038             stopGattProfileService();
1039         }
1040     }
1041 
stateChangeCallback(int status)1042     void stateChangeCallback(int status) {
1043         if (status == AbstractionLayer.BT_STATE_OFF) {
1044             Log.d(TAG, "stateChangeCallback: disableNative() completed");
1045             mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
1046         } else if (status == AbstractionLayer.BT_STATE_ON) {
1047             mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED);
1048         } else {
1049             Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback");
1050         }
1051     }
1052 
startProfileServices()1053     void startProfileServices() {
1054         Log.d(TAG, "startCoreServices()");
1055         int[] supportedProfileServices = Config.getSupportedProfiles();
1056         if (Flags.scanManagerRefactor()) {
1057             // Scanning is always supported, started separately, and is not a profile service.
1058             // This will check other profile services.
1059             if (supportedProfileServices.length == 0) {
1060                 mAdapterProperties.onBluetoothReady();
1061                 updateUuids();
1062                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
1063             } else {
1064                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
1065             }
1066         } else {
1067             // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then
1068             // just move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause
1069             // adapter initialization failures
1070             if (supportedProfileServices.length == 1
1071                     && supportedProfileServices[0] == BluetoothProfile.GATT) {
1072                 mAdapterProperties.onBluetoothReady();
1073                 updateUuids();
1074                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
1075             } else {
1076                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
1077             }
1078         }
1079     }
1080 
stopProfileServices()1081     void stopProfileServices() {
1082         // Make sure to stop classic background tasks now
1083         mNativeInterface.cancelDiscovery();
1084         mAdapterProperties.setScanMode(BluetoothAdapter.SCAN_MODE_NONE);
1085 
1086         int[] supportedProfileServices = Config.getSupportedProfiles();
1087         if (Flags.scanManagerRefactor()) {
1088             // Scanning is always supported, started separately, and is not a profile service.
1089             // This will check other profile services.
1090             if (supportedProfileServices.length == 0) {
1091                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
1092             } else {
1093                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF);
1094             }
1095         } else {
1096             // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just
1097             // move on to BREDR_STOPPED
1098             if (supportedProfileServices.length == 1
1099                     && (mRunningProfiles.size() == 1
1100                             && GattService.class
1101                                     .getSimpleName()
1102                                     .equals(mRunningProfiles.get(0).getName()))) {
1103                 Log.d(
1104                         TAG,
1105                         "stopProfileServices() - No profiles services to stop or already stopped.");
1106                 mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
1107             } else {
1108                 setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF);
1109             }
1110         }
1111     }
1112 
startGattProfileService()1113     private void startGattProfileService() {
1114         mGattService = new GattService(this);
1115 
1116         mStartedProfiles.put(BluetoothProfile.GATT, mGattService);
1117         addProfile(mGattService);
1118         mGattService.start();
1119         mGattService.setAvailable(true);
1120         onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_ON);
1121     }
1122 
startScanController()1123     private void startScanController() {
1124         mScanController = new ScanController(this);
1125         mNativeInterface.enable();
1126     }
1127 
stopGattProfileService()1128     private void stopGattProfileService() {
1129         mAdapterProperties.onBleDisable();
1130         if (mRunningProfiles.size() == 0) {
1131             Log.d(TAG, "stopGattProfileService() - No profiles services to stop.");
1132             mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
1133         }
1134 
1135         mStartedProfiles.remove(BluetoothProfile.GATT);
1136         if (mGattService != null) {
1137             mGattService.setAvailable(false);
1138             onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_OFF);
1139             mGattService.stop();
1140             removeProfile(mGattService);
1141             mGattService.cleanup();
1142             mGattService.getBinder().cleanup();
1143             mGattService = null;
1144         }
1145     }
1146 
stopScanController()1147     private void stopScanController() {
1148         mAdapterProperties.onBleDisable();
1149 
1150         if (mScanController == null) {
1151             mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
1152         } else {
1153             mScanController.stop();
1154             mScanController = null;
1155             mNativeInterface.disable();
1156         }
1157     }
1158 
invalidateBluetoothGetStateCache()1159     private void invalidateBluetoothGetStateCache() {
1160         BluetoothAdapter.invalidateBluetoothGetStateCache();
1161     }
1162 
updateLeAudioProfileServiceState()1163     void updateLeAudioProfileServiceState() {
1164         Set<Integer> nonSupportedProfiles = new HashSet<>();
1165 
1166         if (!isLeConnectedIsochronousStreamCentralSupported()) {
1167             for (int profileId : Config.getLeAudioUnicastProfiles()) {
1168                 nonSupportedProfiles.add(profileId);
1169             }
1170         }
1171 
1172         if (!isLeAudioBroadcastAssistantSupported()) {
1173             nonSupportedProfiles.add(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
1174         }
1175 
1176         if (!isLeAudioBroadcastSourceSupported()) {
1177             Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false);
1178         }
1179 
1180         // Disable the non-supported profiles service
1181         for (int profileId : nonSupportedProfiles) {
1182             Config.setProfileEnabled(profileId, false);
1183             if (mStartedProfiles.containsKey(profileId)) {
1184                 setProfileServiceState(profileId, BluetoothAdapter.STATE_OFF);
1185             }
1186         }
1187     }
1188 
updateAdapterState(int prevState, int newState)1189     void updateAdapterState(int prevState, int newState) {
1190         mAdapterProperties.setState(newState);
1191         invalidateBluetoothGetStateCache();
1192 
1193         // Only BluetoothManagerService should be registered
1194         int n = mRemoteCallbacks.beginBroadcast();
1195         Log.d(
1196                 TAG,
1197                 "updateAdapterState() - Broadcasting state "
1198                         + BluetoothAdapter.nameForState(newState)
1199                         + " to "
1200                         + n
1201                         + " receivers.");
1202         for (int i = 0; i < n; i++) {
1203             try {
1204                 mRemoteCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);
1205             } catch (RemoteException e) {
1206                 Log.d(TAG, "updateAdapterState() - Callback #" + i + " failed (" + e + ")");
1207             }
1208         }
1209         mRemoteCallbacks.finishBroadcast();
1210 
1211         for (Map.Entry<BluetoothStateCallback, Executor> e : mLocalCallbacks.entrySet()) {
1212             e.getValue().execute(() -> e.getKey().onBluetoothStateChange(prevState, newState));
1213         }
1214 
1215         // Turn the Adapter all the way off if we are disabling and the snoop log setting changed.
1216         if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) {
1217             sSnoopLogSettingAtEnable =
1218                     BluetoothProperties.snoop_log_mode()
1219                             .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY);
1220             sDefaultSnoopLogSettingAtEnable =
1221                     Settings.Global.getString(
1222                             getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
1223 
1224             sSnoopLogFilterHeadersSettingAtEnable =
1225                     BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false);
1226             sSnoopLogFilterProfileA2dpSettingAtEnable =
1227                     BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false);
1228             sSnoopLogFilterProfileRfcommSettingAtEnable =
1229                     BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false);
1230             sSnoopLogFilterProfilePbapModeSettingAtEnable =
1231                     BluetoothProperties.snoop_log_filter_profile_pbap()
1232                             .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY);
1233             sSnoopLogFilterProfileMapModeSettingAtEnable =
1234                     BluetoothProperties.snoop_log_filter_profile_map()
1235                             .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY);
1236 
1237             BluetoothProperties.snoop_default_mode(
1238                     BluetoothProperties.snoop_default_mode_values.DISABLED);
1239             for (BluetoothProperties.snoop_default_mode_values value :
1240                     BluetoothProperties.snoop_default_mode_values.values()) {
1241                 if (value.getPropValue().equals(sDefaultSnoopLogSettingAtEnable)) {
1242                     BluetoothProperties.snoop_default_mode(value);
1243                 }
1244             }
1245         } else if (newState == BluetoothAdapter.STATE_BLE_ON
1246                 && prevState != BluetoothAdapter.STATE_OFF) {
1247             var snoopLogSetting =
1248                     BluetoothProperties.snoop_log_mode()
1249                             .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY);
1250             var snoopDefaultModeSetting =
1251                     Settings.Global.getString(
1252                             getContentResolver(), Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
1253 
1254             var snoopLogFilterHeadersSettingAtEnable =
1255                     BluetoothProperties.snoop_log_filter_snoop_headers_enabled().orElse(false);
1256             var snoopLogFilterProfileA2dpSettingAtEnable =
1257                     BluetoothProperties.snoop_log_filter_profile_a2dp_enabled().orElse(false);
1258             var snoopLogFilterProfileRfcommSettingAtEnable =
1259                     BluetoothProperties.snoop_log_filter_profile_rfcomm_enabled().orElse(false);
1260 
1261             var snoopLogFilterProfilePbapModeSetting =
1262                     BluetoothProperties.snoop_log_filter_profile_pbap()
1263                             .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.EMPTY);
1264             var snoopLogFilterProfileMapModeSetting =
1265                     BluetoothProperties.snoop_log_filter_profile_map()
1266                             .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.EMPTY);
1267 
1268             if (!(sSnoopLogSettingAtEnable == snoopLogSetting)
1269                     || !(sDefaultSnoopLogSettingAtEnable == snoopDefaultModeSetting)
1270                     || !(sSnoopLogFilterHeadersSettingAtEnable
1271                             == snoopLogFilterHeadersSettingAtEnable)
1272                     || !(sSnoopLogFilterProfileA2dpSettingAtEnable
1273                             == snoopLogFilterProfileA2dpSettingAtEnable)
1274                     || !(sSnoopLogFilterProfileRfcommSettingAtEnable
1275                             == snoopLogFilterProfileRfcommSettingAtEnable)
1276                     || !(sSnoopLogFilterProfilePbapModeSettingAtEnable
1277                             == snoopLogFilterProfilePbapModeSetting)
1278                     || !(sSnoopLogFilterProfileMapModeSettingAtEnable
1279                             == snoopLogFilterProfileMapModeSetting)) {
1280                 mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
1281             }
1282         }
1283     }
1284 
linkQualityReportCallback( long timestamp, int reportId, int rssi, int snr, int retransmissionCount, int packetsNotReceiveCount, int negativeAcknowledgementCount)1285     void linkQualityReportCallback(
1286             long timestamp,
1287             int reportId,
1288             int rssi,
1289             int snr,
1290             int retransmissionCount,
1291             int packetsNotReceiveCount,
1292             int negativeAcknowledgementCount) {
1293         BluetoothInCallService bluetoothInCallService = BluetoothInCallService.getInstance();
1294 
1295         if (reportId == BqrQualityReportId.QUALITY_REPORT_ID_SCO_VOICE_CHOPPY.getValue()) {
1296             if (bluetoothInCallService == null) {
1297                 Log.w(
1298                         TAG,
1299                         "No BluetoothInCallService while trying to send BQR."
1300                                 + (" timestamp: " + timestamp)
1301                                 + (" reportId: " + reportId)
1302                                 + (" rssi: " + rssi)
1303                                 + (" snr: " + snr)
1304                                 + (" retransmissionCount: " + retransmissionCount)
1305                                 + (" packetsNotReceiveCount: " + packetsNotReceiveCount)
1306                                 + (" negativeAcknowledgementCount: "
1307                                         + negativeAcknowledgementCount));
1308                 return;
1309             }
1310             bluetoothInCallService.sendBluetoothCallQualityReport(
1311                     timestamp,
1312                     rssi,
1313                     snr,
1314                     retransmissionCount,
1315                     packetsNotReceiveCount,
1316                     negativeAcknowledgementCount);
1317         }
1318     }
1319 
1320     /**
1321      * Callback from Bluetooth Quality Report Native Interface to inform the listeners about
1322      * Bluetooth Quality.
1323      *
1324      * @param device is the BluetoothDevice which connection quality is being reported
1325      * @param bluetoothQualityReport a Parcel that contains information about Bluetooth Quality
1326      * @return whether the Bluetooth stack acknowledged the change successfully
1327      */
bluetoothQualityReportReadyCallback( BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport)1328     public int bluetoothQualityReportReadyCallback(
1329             BluetoothDevice device, BluetoothQualityReport bluetoothQualityReport) {
1330         synchronized (mBluetoothQualityReportReadyCallbacks) {
1331             int n = mBluetoothQualityReportReadyCallbacks.beginBroadcast();
1332             Log.d(
1333                     TAG,
1334                     "bluetoothQualityReportReadyCallback() - "
1335                             + "Broadcasting Bluetooth Quality Report to "
1336                             + n
1337                             + " receivers.");
1338             for (int i = 0; i < n; i++) {
1339                 try {
1340                     mBluetoothQualityReportReadyCallbacks
1341                             .getBroadcastItem(i)
1342                             .onBluetoothQualityReportReady(
1343                                     device, bluetoothQualityReport, BluetoothStatusCodes.SUCCESS);
1344                 } catch (RemoteException e) {
1345                     Log.d(
1346                             TAG,
1347                             "bluetoothQualityReportReadyCallback() - Callback #"
1348                                     + i
1349                                     + " failed ("
1350                                     + e
1351                                     + ")");
1352                 }
1353             }
1354             mBluetoothQualityReportReadyCallbacks.finishBroadcast();
1355         }
1356 
1357         return BluetoothStatusCodes.SUCCESS;
1358     }
1359 
switchBufferSizeCallback(boolean isLowLatencyBufferSize)1360     void switchBufferSizeCallback(boolean isLowLatencyBufferSize) {
1361         List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP);
1362         if (activeDevices.size() != 1) {
1363             Log.e(
1364                     TAG,
1365                     "Cannot switch buffer size. The number of A2DP active devices is "
1366                             + activeDevices.size());
1367             return;
1368         }
1369 
1370         // Send intent to fastpair
1371         Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE);
1372         switchBufferSizeIntent.setClassName(
1373                 getString(com.android.bluetooth.R.string.peripheral_link_package),
1374                 getString(com.android.bluetooth.R.string.peripheral_link_package)
1375                         + getString(com.android.bluetooth.R.string.peripheral_link_service));
1376         switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, activeDevices.get(0));
1377         switchBufferSizeIntent.putExtra(
1378                 BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize);
1379         sendBroadcastMultiplePermissions(
1380                 switchBufferSizeIntent,
1381                 new String[] {
1382                     android.Manifest.permission.BLUETOOTH_CONNECT,
1383                     android.Manifest.permission.BLUETOOTH_PRIVILEGED
1384                 },
1385                 null);
1386     }
1387 
switchCodecCallback(boolean isLowLatencyBufferSize)1388     void switchCodecCallback(boolean isLowLatencyBufferSize) {
1389         List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP);
1390         if (activeDevices.size() != 1) {
1391             Log.e(
1392                     TAG,
1393                     "Cannot switch buffer size. The number of A2DP active devices is "
1394                             + activeDevices.size());
1395             return;
1396         }
1397         mA2dpService.switchCodecByBufferSize(activeDevices.get(0), isLowLatencyBufferSize);
1398     }
1399 
1400     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
cleanup()1401     void cleanup() {
1402         Log.d(TAG, "cleanup()");
1403         if (mCleaningUp) {
1404             Log.e(TAG, "cleanup() - Service already starting to cleanup, ignoring request...");
1405             return;
1406         }
1407 
1408         closeMetricsLogger();
1409 
1410         clearAdapterService(this);
1411 
1412         mCleaningUp = true;
1413         invalidateBluetoothCaches();
1414 
1415         stopRfcommServerSockets();
1416 
1417         // This wake lock release may also be called concurrently by
1418         // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here.
1419         synchronized (this) {
1420             if (mWakeLock != null) {
1421                 if (mWakeLock.isHeld()) {
1422                     mWakeLock.release();
1423                 }
1424                 mWakeLock = null;
1425             }
1426         }
1427 
1428         mDatabaseManager.cleanup();
1429 
1430         if (mAdapterStateMachine != null) {
1431             mAdapterStateMachine.doQuit();
1432         }
1433 
1434         if (mBondStateMachine != null) {
1435             mBondStateMachine.doQuit();
1436         }
1437 
1438         if (mRemoteDevices != null) {
1439             mRemoteDevices.reset();
1440         }
1441 
1442         if (mSdpManager != null) {
1443             mSdpManager.cleanup();
1444             mSdpManager = null;
1445         }
1446 
1447         if (mNativeAvailable) {
1448             Log.d(TAG, "cleanup() - Cleaning up adapter native");
1449             mNativeInterface.cleanup();
1450             mNativeAvailable = false;
1451         }
1452 
1453         if (mAdapterProperties != null) {
1454             mAdapterProperties.cleanup();
1455         }
1456 
1457         if (mNativeInterface.getCallbacks() != null) {
1458             mNativeInterface.getCallbacks().cleanup();
1459         }
1460 
1461         if (mBluetoothKeystoreService != null) {
1462             Log.d(TAG, "cleanup(): mBluetoothKeystoreService.cleanup()");
1463             mBluetoothKeystoreService.cleanup();
1464         }
1465 
1466         if (mPhonePolicy != null) {
1467             mPhonePolicy.cleanup();
1468         }
1469 
1470         mSilenceDeviceManager.cleanup();
1471 
1472         if (mActiveDeviceManager != null) {
1473             mActiveDeviceManager.cleanup();
1474         }
1475 
1476         if (mBluetoothSocketManagerBinder != null) {
1477             mBluetoothSocketManagerBinder.cleanUp();
1478             mBluetoothSocketManagerBinder = null;
1479         }
1480 
1481         if (!Flags.explicitKillFromSystemServer()) {
1482             // Bluetooth will be killed, no need to cleanup binder
1483             if (mBinder != null) {
1484                 mBinder.cleanup();
1485                 mBinder = null; // Do not remove. Otherwise Binder leak!
1486             }
1487         }
1488 
1489         mPreferredAudioProfilesCallbacks.kill();
1490 
1491         mBluetoothQualityReportReadyCallbacks.kill();
1492 
1493         mRemoteCallbacks.kill();
1494     }
1495 
invalidateBluetoothCaches()1496     private void invalidateBluetoothCaches() {
1497         BluetoothAdapter.invalidateGetProfileConnectionStateCache();
1498         BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache();
1499         BluetoothDevice.invalidateBluetoothGetBondStateCache();
1500         BluetoothAdapter.invalidateBluetoothGetStateCache();
1501         BluetoothAdapter.invalidateGetAdapterConnectionStateCache();
1502         BluetoothMap.invalidateBluetoothGetConnectionStateCache();
1503         BluetoothSap.invalidateBluetoothGetConnectionStateCache();
1504     }
1505 
1506     private static final Map<Integer, Function<AdapterService, ProfileService>>
1507             PROFILE_CONSTRUCTORS =
1508                     Map.ofEntries(
1509                             Map.entry(BluetoothProfile.A2DP, A2dpService::new),
1510                             Map.entry(BluetoothProfile.A2DP_SINK, A2dpSinkService::new),
1511                             Map.entry(BluetoothProfile.AVRCP, AvrcpTargetService::new),
1512                             Map.entry(
1513                                     BluetoothProfile.AVRCP_CONTROLLER, AvrcpControllerService::new),
1514                             Map.entry(
1515                                     BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT,
1516                                     BassClientService::new),
1517                             Map.entry(BluetoothProfile.BATTERY, BatteryService::new),
1518                             Map.entry(
1519                                     BluetoothProfile.CSIP_SET_COORDINATOR,
1520                                     CsipSetCoordinatorService::new),
1521                             Map.entry(BluetoothProfile.HAP_CLIENT, HapClientService::new),
1522                             Map.entry(BluetoothProfile.HEADSET, HeadsetService::new),
1523                             Map.entry(BluetoothProfile.HEADSET_CLIENT, HeadsetClientService::new),
1524                             Map.entry(BluetoothProfile.HEARING_AID, HearingAidService::new),
1525                             Map.entry(BluetoothProfile.HID_DEVICE, HidDeviceService::new),
1526                             Map.entry(BluetoothProfile.HID_HOST, HidHostService::new),
1527                             Map.entry(BluetoothProfile.GATT, GattService::new),
1528                             Map.entry(BluetoothProfile.LE_AUDIO, LeAudioService::new),
1529                             Map.entry(BluetoothProfile.LE_CALL_CONTROL, TbsService::new),
1530                             Map.entry(BluetoothProfile.MAP, BluetoothMapService::new),
1531                             Map.entry(BluetoothProfile.MAP_CLIENT, MapClientService::new),
1532                             Map.entry(BluetoothProfile.MCP_SERVER, McpService::new),
1533                             Map.entry(BluetoothProfile.OPP, BluetoothOppService::new),
1534                             Map.entry(BluetoothProfile.PAN, PanService::new),
1535                             Map.entry(BluetoothProfile.PBAP, BluetoothPbapService::new),
1536                             Map.entry(BluetoothProfile.PBAP_CLIENT, PbapClientService::new),
1537                             Map.entry(BluetoothProfile.SAP, SapService::new),
1538                             Map.entry(BluetoothProfile.VOLUME_CONTROL, VolumeControlService::new));
1539 
1540     @VisibleForTesting
setProfileServiceState(int profileId, int state)1541     void setProfileServiceState(int profileId, int state) {
1542         if (state == BluetoothAdapter.STATE_ON) {
1543             if (!mStartedProfiles.containsKey(profileId)) {
1544                 ProfileService profileService = PROFILE_CONSTRUCTORS.get(profileId).apply(this);
1545                 mStartedProfiles.put(profileId, profileService);
1546                 addProfile(profileService);
1547                 profileService.start();
1548                 profileService.setAvailable(true);
1549                 onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_ON);
1550             } else {
1551                 Log.e(
1552                         TAG,
1553                         "setProfileServiceState("
1554                                 + BluetoothProfile.getProfileName(profileId)
1555                                 + ", STATE_ON): profile is already started");
1556             }
1557         } else if (state == BluetoothAdapter.STATE_OFF) {
1558             ProfileService profileService = mStartedProfiles.remove(profileId);
1559             if (profileService != null) {
1560                 profileService.setAvailable(false);
1561                 onProfileServiceStateChanged(profileService, BluetoothAdapter.STATE_OFF);
1562                 profileService.stop();
1563                 removeProfile(profileService);
1564                 profileService.cleanup();
1565                 profileService.getBinder().cleanup();
1566             } else {
1567                 Log.e(
1568                         TAG,
1569                         "setProfileServiceState("
1570                                 + BluetoothProfile.getProfileName(profileId)
1571                                 + ", STATE_OFF): profile is already stopped");
1572             }
1573         }
1574     }
1575 
setAllProfileServiceStates(int[] profileIds, int state)1576     private void setAllProfileServiceStates(int[] profileIds, int state) {
1577         for (int profileId : profileIds) {
1578             if (!Flags.scanManagerRefactor()) {
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
1661     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
isProfileSupported(BluetoothDevice device, int profile)1662     boolean isProfileSupported(BluetoothDevice device, int profile) {
1663         ParcelUuid[] remoteDeviceUuids = getRemoteUuids(device);
1664         ParcelUuid[] localDeviceUuids = mAdapterProperties.getUuids();
1665         if (remoteDeviceUuids == null || remoteDeviceUuids.length == 0) {
1666             Log.e(
1667                     TAG,
1668                     "isProfileSupported("
1669                             + ("device=" + device)
1670                             + (", profile=" + BluetoothProfile.getProfileName(profile) + "):")
1671                             + " remote device Uuids Empty");
1672         }
1673 
1674         Log.v(
1675                 TAG,
1676                 "isProfileSupported("
1677                         + ("device=" + device)
1678                         + (", profile=" + BluetoothProfile.getProfileName(profile) + "):")
1679                         + (" local_uuids=" + Arrays.toString(localDeviceUuids))
1680                         + (", remote_uuids=" + Arrays.toString(remoteDeviceUuids)));
1681 
1682         if (profile == BluetoothProfile.HEADSET) {
1683             return (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HSP_AG)
1684                             && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HSP))
1685                     || (Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP_AG)
1686                             && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP));
1687         }
1688         if (profile == BluetoothProfile.HEADSET_CLIENT) {
1689             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HFP_AG)
1690                     && Utils.arrayContains(localDeviceUuids, BluetoothUuid.HFP);
1691         }
1692         if (profile == BluetoothProfile.A2DP) {
1693             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST)
1694                     || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SINK);
1695         }
1696         if (profile == BluetoothProfile.A2DP_SINK) {
1697             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.ADV_AUDIO_DIST)
1698                     || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.A2DP_SOURCE);
1699         }
1700         if (profile == BluetoothProfile.OPP) {
1701             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.OBEX_OBJECT_PUSH);
1702         }
1703         if (profile == BluetoothProfile.HID_HOST) {
1704             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HID)
1705                     || Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HOGP)
1706                     || (Flags.androidHeadtrackerService()
1707                             && Utils.arrayContains(
1708                                     remoteDeviceUuids, HidHostService.ANDROID_HEADTRACKER_UUID));
1709         }
1710         if (profile == BluetoothProfile.HID_DEVICE) {
1711             return mHidDeviceService.getConnectionState(device)
1712                     == BluetoothProfile.STATE_DISCONNECTED;
1713         }
1714         if (profile == BluetoothProfile.PAN) {
1715             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.NAP);
1716         }
1717         if (profile == BluetoothProfile.MAP) {
1718             return mMapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED;
1719         }
1720         if (profile == BluetoothProfile.PBAP) {
1721             return mPbapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED;
1722         }
1723         if (profile == BluetoothProfile.MAP_CLIENT) {
1724             return Utils.arrayContains(localDeviceUuids, BluetoothUuid.MNS)
1725                     && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.MAS);
1726         }
1727         if (profile == BluetoothProfile.PBAP_CLIENT) {
1728             return Utils.arrayContains(localDeviceUuids, BluetoothUuid.PBAP_PCE)
1729                     && Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.PBAP_PSE);
1730         }
1731         if (profile == BluetoothProfile.HEARING_AID) {
1732             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HEARING_AID);
1733         }
1734         if (profile == BluetoothProfile.SAP) {
1735             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.SAP);
1736         }
1737         if (profile == BluetoothProfile.VOLUME_CONTROL) {
1738             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.VOLUME_CONTROL);
1739         }
1740         if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) {
1741             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET);
1742         }
1743         if (profile == BluetoothProfile.LE_AUDIO) {
1744             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO);
1745         }
1746         if (profile == BluetoothProfile.HAP_CLIENT) {
1747             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS);
1748         }
1749         if (profile == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT) {
1750             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BASS);
1751         }
1752         if (profile == BluetoothProfile.BATTERY) {
1753             return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.BATTERY);
1754         }
1755 
1756         Log.e(TAG, "isSupported: Unexpected profile passed in to function: " + profile);
1757         return false;
1758     }
1759 
1760     /**
1761      * Checks if the connection policy of all profiles are unknown for the given device
1762      *
1763      * @param device is the device for which we are checking if the connection policy of all
1764      *     profiles are unknown
1765      * @return false if one of profile is enabled or disabled, true otherwise
1766      */
1767     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
isAllProfilesUnknown(BluetoothDevice device)1768     boolean isAllProfilesUnknown(BluetoothDevice device) {
1769         if (mA2dpService != null
1770                 && mA2dpService.getConnectionPolicy(device)
1771                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1772             return false;
1773         }
1774         if (mA2dpSinkService != null
1775                 && mA2dpSinkService.getConnectionPolicy(device)
1776                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1777             return false;
1778         }
1779         if (mHeadsetService != null
1780                 && mHeadsetService.getConnectionPolicy(device)
1781                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1782             return false;
1783         }
1784         if (mHeadsetClientService != null
1785                 && mHeadsetClientService.getConnectionPolicy(device)
1786                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1787             return false;
1788         }
1789         if (mMapClientService != null
1790                 && mMapClientService.getConnectionPolicy(device)
1791                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1792             return false;
1793         }
1794         if (mHidHostService != null
1795                 && mHidHostService.getConnectionPolicy(device)
1796                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1797             return false;
1798         }
1799         if (mPanService != null
1800                 && mPanService.getConnectionPolicy(device)
1801                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1802             return false;
1803         }
1804         if (mPbapClientService != null
1805                 && mPbapClientService.getConnectionPolicy(device)
1806                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1807             return false;
1808         }
1809         if (mHearingAidService != null
1810                 && mHearingAidService.getConnectionPolicy(device)
1811                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1812             return false;
1813         }
1814         if (mHapClientService != null
1815                 && mHapClientService.getConnectionPolicy(device)
1816                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1817             return false;
1818         }
1819         if (mVolumeControlService != null
1820                 && mVolumeControlService.getConnectionPolicy(device)
1821                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1822             return false;
1823         }
1824         if (mCsipSetCoordinatorService != null
1825                 && mCsipSetCoordinatorService.getConnectionPolicy(device)
1826                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1827             return false;
1828         }
1829         if (mLeAudioService != null
1830                 && mLeAudioService.getConnectionPolicy(device)
1831                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1832             return false;
1833         }
1834         if (mBassClientService != null
1835                 && mBassClientService.getConnectionPolicy(device)
1836                         != BluetoothProfile.CONNECTION_POLICY_UNKNOWN) {
1837             return false;
1838         }
1839         return true;
1840     }
1841 
1842     /**
1843      * Connects only available profiles (those with {@link
1844      * BluetoothProfile#CONNECTION_POLICY_ALLOWED})
1845      *
1846      * @param device is the device with which we are connecting the profiles
1847      * @return {@link BluetoothStatusCodes#SUCCESS}
1848      */
1849     @RequiresPermission(
1850             allOf = {
1851                 android.Manifest.permission.BLUETOOTH_PRIVILEGED,
1852                 android.Manifest.permission.MODIFY_PHONE_STATE,
1853             })
connectEnabledProfiles(BluetoothDevice device)1854     private int connectEnabledProfiles(BluetoothDevice device) {
1855         if (mCsipSetCoordinatorService != null
1856                 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR)
1857                 && mCsipSetCoordinatorService.getConnectionPolicy(device)
1858                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1859             Log.i(TAG, "connectEnabledProfiles: Connecting Coordinated Set Profile");
1860             mCsipSetCoordinatorService.connect(device);
1861         }
1862         if (mA2dpService != null
1863                 && isProfileSupported(device, BluetoothProfile.A2DP)
1864                 && mA2dpService.getConnectionPolicy(device)
1865                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1866             Log.i(TAG, "connectEnabledProfiles: Connecting A2dp");
1867             mA2dpService.connect(device);
1868         }
1869         if (mA2dpSinkService != null
1870                 && isProfileSupported(device, BluetoothProfile.A2DP_SINK)
1871                 && mA2dpSinkService.getConnectionPolicy(device)
1872                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1873             Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink");
1874             mA2dpSinkService.connect(device);
1875         }
1876         if (mHeadsetService != null
1877                 && isProfileSupported(device, BluetoothProfile.HEADSET)
1878                 && mHeadsetService.getConnectionPolicy(device)
1879                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1880             Log.i(TAG, "connectEnabledProfiles: Connecting Headset Profile");
1881             mHeadsetService.connect(device);
1882         }
1883         if (mHeadsetClientService != null
1884                 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT)
1885                 && mHeadsetClientService.getConnectionPolicy(device)
1886                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1887             Log.i(TAG, "connectEnabledProfiles: Connecting HFP");
1888             mHeadsetClientService.connect(device);
1889         }
1890         if (mMapClientService != null
1891                 && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)
1892                 && mMapClientService.getConnectionPolicy(device)
1893                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1894             Log.i(TAG, "connectEnabledProfiles: Connecting MAP");
1895             mMapClientService.connect(device);
1896         }
1897         if (mHidHostService != null
1898                 && isProfileSupported(device, BluetoothProfile.HID_HOST)
1899                 && mHidHostService.getConnectionPolicy(device)
1900                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1901             Log.i(TAG, "connectEnabledProfiles: Connecting Hid Host Profile");
1902             mHidHostService.connect(device);
1903         }
1904         if (mPanService != null
1905                 && isProfileSupported(device, BluetoothProfile.PAN)
1906                 && mPanService.getConnectionPolicy(device)
1907                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1908             Log.i(TAG, "connectEnabledProfiles: Connecting Pan Profile");
1909             mPanService.connect(device);
1910         }
1911         if (mPbapClientService != null
1912                 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT)
1913                 && mPbapClientService.getConnectionPolicy(device)
1914                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1915             Log.i(TAG, "connectEnabledProfiles: Connecting Pbap");
1916             mPbapClientService.connect(device);
1917         }
1918         if (mHearingAidService != null
1919                 && isProfileSupported(device, BluetoothProfile.HEARING_AID)
1920                 && mHearingAidService.getConnectionPolicy(device)
1921                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1922             Log.i(TAG, "connectEnabledProfiles: Connecting Hearing Aid Profile");
1923             mHearingAidService.connect(device);
1924         }
1925         if (mHapClientService != null
1926                 && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)
1927                 && mHapClientService.getConnectionPolicy(device)
1928                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1929             Log.i(TAG, "connectEnabledProfiles: Connecting HAS Profile");
1930             mHapClientService.connect(device);
1931         }
1932         if (mVolumeControlService != null
1933                 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL)
1934                 && mVolumeControlService.getConnectionPolicy(device)
1935                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1936             Log.i(TAG, "connectEnabledProfiles: Connecting Volume Control Profile");
1937             mVolumeControlService.connect(device);
1938         }
1939         if (mLeAudioService != null
1940                 && isProfileSupported(device, BluetoothProfile.LE_AUDIO)
1941                 && mLeAudioService.getConnectionPolicy(device)
1942                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1943             Log.i(TAG, "connectEnabledProfiles: Connecting LeAudio profile (BAP)");
1944             mLeAudioService.connect(device);
1945         }
1946         if (mBassClientService != null
1947                 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)
1948                 && mBassClientService.getConnectionPolicy(device)
1949                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1950             Log.i(TAG, "connectEnabledProfiles: Connecting LE Broadcast Assistant Profile");
1951             mBassClientService.connect(device);
1952         }
1953         if (mBatteryService != null
1954                 && isProfileSupported(device, BluetoothProfile.BATTERY)
1955                 && mBatteryService.getConnectionPolicy(device)
1956                         > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
1957             Log.i(TAG, "connectEnabledProfiles: Connecting Battery Service");
1958             mBatteryService.connect(device);
1959         }
1960         return BluetoothStatusCodes.SUCCESS;
1961     }
1962 
1963     /**
1964      * Verifies that all bluetooth profile services are running
1965      *
1966      * @return true if all bluetooth profile services running, false otherwise
1967      */
profileServicesRunning()1968     private boolean profileServicesRunning() {
1969         if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
1970                 && mRegisteredProfiles.size() == mRunningProfiles.size()) {
1971             return true;
1972         }
1973 
1974         Log.e(TAG, "profileServicesRunning: One or more supported services not running");
1975         return false;
1976     }
1977 
1978     /** Initializes all the profile services fields */
initProfileServices()1979     private void initProfileServices() {
1980         Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services");
1981         mA2dpService = A2dpService.getA2dpService();
1982         mA2dpSinkService = A2dpSinkService.getA2dpSinkService();
1983         mHeadsetService = HeadsetService.getHeadsetService();
1984         mHeadsetClientService = HeadsetClientService.getHeadsetClientService();
1985         mMapService = BluetoothMapService.getBluetoothMapService();
1986         mMapClientService = MapClientService.getMapClientService();
1987         mHidDeviceService = HidDeviceService.getHidDeviceService();
1988         mHidHostService = HidHostService.getHidHostService();
1989         mPanService = PanService.getPanService();
1990         mPbapService = BluetoothPbapService.getBluetoothPbapService();
1991         mPbapClientService = PbapClientService.getPbapClientService();
1992         mHearingAidService = HearingAidService.getHearingAidService();
1993         mHapClientService = HapClientService.getHapClientService();
1994         mSapService = SapService.getSapService();
1995         mVolumeControlService = VolumeControlService.getVolumeControlService();
1996         mCsipSetCoordinatorService = CsipSetCoordinatorService.getCsipSetCoordinatorService();
1997         mLeAudioService = LeAudioService.getLeAudioService();
1998         mBassClientService = BassClientService.getBassClientService();
1999         mBatteryService = BatteryService.getBatteryService();
2000         if (Flags.scanManagerRefactor()) {
2001             mGattService = GattService.getGattService();
2002         }
2003     }
2004 
2005     @BluetoothAdapter.RfcommListenerResult
2006     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource)2007     private int startRfcommListener(
2008             String name,
2009             ParcelUuid uuid,
2010             PendingIntent pendingIntent,
2011             AttributionSource attributionSource) {
2012         if (mBluetoothServerSockets.containsKey(uuid.getUuid())) {
2013             Log.d(
2014                     TAG,
2015                     String.format(
2016                             "Cannot start RFCOMM listener: UUID %s already in use.",
2017                             uuid.getUuid()));
2018             return BluetoothStatusCodes.RFCOMM_LISTENER_START_FAILED_UUID_IN_USE;
2019         }
2020 
2021         try {
2022             startRfcommListenerInternal(name, uuid.getUuid(), pendingIntent, attributionSource);
2023         } catch (IOException e) {
2024             return BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CREATE_SERVER_SOCKET;
2025         }
2026 
2027         return BluetoothStatusCodes.SUCCESS;
2028     }
2029 
2030     @BluetoothAdapter.RfcommListenerResult
2031     @VisibleForTesting
stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource)2032     int stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource) {
2033         RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid());
2034 
2035         if (listenerData == null) {
2036             Log.d(
2037                     TAG,
2038                     String.format(
2039                             "Cannot stop RFCOMM listener: UUID %s is not registered.",
2040                             uuid.getUuid()));
2041             return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD;
2042         }
2043 
2044         if (attributionSource.getUid() != listenerData.mAttributionSource.getUid()) {
2045             return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP;
2046         }
2047 
2048         // Remove the entry so that it does not try and restart the server socket.
2049         mBluetoothServerSockets.remove(uuid.getUuid());
2050 
2051         return listenerData.closeServerAndPendingSockets(mHandler);
2052     }
2053 
2054     @VisibleForTesting
retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource attributionSource)2055     IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord(
2056             ParcelUuid uuid, AttributionSource attributionSource) {
2057         IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo();
2058 
2059         RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid());
2060 
2061         if (listenerData == null) {
2062             socketInfo.status =
2063                     BluetoothStatusCodes
2064                             .RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD;
2065             return socketInfo;
2066         }
2067 
2068         if (attributionSource.getUid() != listenerData.mAttributionSource.getUid()) {
2069             socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP;
2070             return socketInfo;
2071         }
2072 
2073         BluetoothSocket socket = listenerData.mPendingSockets.poll();
2074 
2075         if (socket == null) {
2076             socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE;
2077             return socketInfo;
2078         }
2079 
2080         mHandler.removeCallbacksAndMessages(socket);
2081 
2082         socketInfo.bluetoothDevice = socket.getRemoteDevice();
2083         socketInfo.pfd = socket.getParcelFileDescriptor();
2084         socketInfo.status = BluetoothStatusCodes.SUCCESS;
2085 
2086         return socketInfo;
2087     }
2088 
2089     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
handleIncomingRfcommConnections(UUID uuid)2090     private void handleIncomingRfcommConnections(UUID uuid) {
2091         RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid);
2092         while (true) {
2093             BluetoothSocket socket;
2094             try {
2095                 socket = listenerData.mServerSocket.accept();
2096             } catch (IOException e) {
2097                 if (mBluetoothServerSockets.containsKey(uuid)) {
2098                     // The uuid still being in the map indicates that the accept failure is
2099                     // unexpected. Try and restart the listener.
2100                     Log.e(TAG, "Failed to accept socket on " + listenerData.mServerSocket, e);
2101                     restartRfcommListener(listenerData, uuid);
2102                 }
2103                 return;
2104             }
2105 
2106             listenerData.mPendingSockets.add(socket);
2107             try {
2108                 listenerData.mPendingIntent.send();
2109             } catch (PendingIntent.CanceledException e) {
2110                 Log.e(TAG, "PendingIntent for RFCOMM socket notifications cancelled.", e);
2111                 // The pending intent was cancelled, close the server as there is no longer any way
2112                 // to notify the app that registered the listener.
2113                 listenerData.closeServerAndPendingSockets(mHandler);
2114                 mBluetoothServerSockets.remove(uuid);
2115                 return;
2116             }
2117             mHandler.postDelayed(
2118                     () -> pendingSocketTimeoutRunnable(listenerData, socket),
2119                     socket,
2120                     PENDING_SOCKET_HANDOFF_TIMEOUT.toMillis());
2121         }
2122     }
2123 
2124     // Tries to restart the rfcomm listener for the given UUID
2125     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
restartRfcommListener(RfcommListenerData listenerData, UUID uuid)2126     private void restartRfcommListener(RfcommListenerData listenerData, UUID uuid) {
2127         listenerData.closeServerAndPendingSockets(mHandler);
2128         try {
2129             startRfcommListenerInternal(
2130                     listenerData.mName,
2131                     uuid,
2132                     listenerData.mPendingIntent,
2133                     listenerData.mAttributionSource);
2134         } catch (IOException e) {
2135             Log.e(TAG, "Failed to recreate rfcomm server socket", e);
2136 
2137             mBluetoothServerSockets.remove(uuid);
2138         }
2139     }
2140 
pendingSocketTimeoutRunnable( RfcommListenerData listenerData, BluetoothSocket socket)2141     private void pendingSocketTimeoutRunnable(
2142             RfcommListenerData listenerData, BluetoothSocket socket) {
2143         boolean socketFound = listenerData.mPendingSockets.remove(socket);
2144         if (socketFound) {
2145             try {
2146                 socket.close();
2147             } catch (IOException e) {
2148                 Log.e(TAG, "Failed to close bt socket", e);
2149                 // We don't care if closing the socket failed, just continue on.
2150             }
2151         }
2152     }
2153 
2154     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
startRfcommListenerInternal( String name, UUID uuid, PendingIntent intent, AttributionSource attributionSource)2155     private void startRfcommListenerInternal(
2156             String name, UUID uuid, PendingIntent intent, AttributionSource attributionSource)
2157             throws IOException {
2158         BluetoothServerSocket bluetoothServerSocket =
2159                 mAdapter.listenUsingRfcommWithServiceRecord(name, uuid);
2160 
2161         RfcommListenerData listenerData =
2162                 new RfcommListenerData(bluetoothServerSocket, name, intent, attributionSource);
2163 
2164         mBluetoothServerSockets.put(uuid, listenerData);
2165 
2166         new Thread(() -> handleIncomingRfcommConnections(uuid)).start();
2167     }
2168 
stopRfcommServerSockets()2169     private void stopRfcommServerSockets() {
2170         Iterator<Map.Entry<UUID, RfcommListenerData>> socketsIterator =
2171                 mBluetoothServerSockets.entrySet().iterator();
2172         while (socketsIterator.hasNext()) {
2173             socketsIterator.next().getValue().closeServerAndPendingSockets(mHandler);
2174             socketsIterator.remove();
2175         }
2176     }
2177 
2178     private static class RfcommListenerData {
2179         final BluetoothServerSocket mServerSocket;
2180         // Service record name
2181         final String mName;
2182         // The Intent which contains the Service info to which the incoming socket connections are
2183         // handed off to.
2184         final PendingIntent mPendingIntent;
2185         // AttributionSource for the requester of the RFCOMM listener
2186         final AttributionSource mAttributionSource;
2187         // Contains the connected sockets which are pending transfer to the app which requested the
2188         // listener.
2189         final ConcurrentLinkedQueue<BluetoothSocket> mPendingSockets =
2190                 new ConcurrentLinkedQueue<>();
2191 
RfcommListenerData( BluetoothServerSocket serverSocket, String name, PendingIntent pendingIntent, AttributionSource attributionSource)2192         RfcommListenerData(
2193                 BluetoothServerSocket serverSocket,
2194                 String name,
2195                 PendingIntent pendingIntent,
2196                 AttributionSource attributionSource) {
2197             mServerSocket = serverSocket;
2198             mName = name;
2199             mPendingIntent = pendingIntent;
2200             mAttributionSource = attributionSource;
2201         }
2202 
closeServerAndPendingSockets(Handler handler)2203         int closeServerAndPendingSockets(Handler handler) {
2204             int result = BluetoothStatusCodes.SUCCESS;
2205             try {
2206                 mServerSocket.close();
2207             } catch (IOException e) {
2208                 Log.e(TAG, "Failed to call close on rfcomm server socket", e);
2209                 result = BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET;
2210             }
2211             mPendingSockets.forEach(
2212                     pendingSocket -> {
2213                         handler.removeCallbacksAndMessages(pendingSocket);
2214                         try {
2215                             pendingSocket.close();
2216                         } catch (IOException e) {
2217                             Log.e(TAG, "Failed to close socket", e);
2218                         }
2219                     });
2220             mPendingSockets.clear();
2221 
2222             return result;
2223         }
2224     }
2225 
2226     @VisibleForTesting
isAvailable()2227     boolean isAvailable() {
2228         return !mCleaningUp;
2229     }
2230 
2231     /**
2232      * Get an metadata of given device and key
2233      *
2234      * @param device Bluetooth device
2235      * @param key Metadata key
2236      * @param value Metadata value
2237      * @return if metadata is set successfully
2238      */
setMetadata(BluetoothDevice device, int key, byte[] value)2239     public boolean setMetadata(BluetoothDevice device, int key, byte[] value) {
2240         if (value == null || value.length > BluetoothDevice.METADATA_MAX_LENGTH) {
2241             return false;
2242         }
2243         return mDatabaseManager.setCustomMeta(device, key, value);
2244     }
2245 
2246     /**
2247      * Get an metadata of given device and key
2248      *
2249      * @param device Bluetooth device
2250      * @param key Metadata key
2251      * @return value of given device and key combination
2252      */
getMetadata(BluetoothDevice device, int key)2253     public byte[] getMetadata(BluetoothDevice device, int key) {
2254         return mDatabaseManager.getCustomMeta(device, key);
2255     }
2256 
2257     /** Update Adapter Properties when BT profiles connection state changes. */
updateProfileConnectionAdapterProperties( BluetoothDevice device, int profile, int state, int prevState)2258     public void updateProfileConnectionAdapterProperties(
2259             BluetoothDevice device, int profile, int state, int prevState) {
2260         mHandler.post(
2261                 () ->
2262                         mAdapterProperties.updateOnProfileConnectionChanged(
2263                                 device, profile, state, prevState));
2264     }
2265 
2266     /**
2267      * The Binder implementation must be declared to be a static class, with the AdapterService
2268      * instance passed in the constructor. Furthermore, when the AdapterService shuts down, the
2269      * reference to the AdapterService must be explicitly removed.
2270      *
2271      * <p>Otherwise, a memory leak can occur from repeated starting/stopping the service...Please
2272      * refer to android.os.Binder for further details on why an inner instance class should be
2273      * avoided.
2274      *
2275      * <p>TODO: b/339548431 -- Delete this comment as it does not apply when we get killed
2276      */
2277     @VisibleForTesting
2278     public static class AdapterServiceBinder extends IBluetooth.Stub {
2279         // TODO: b/339548431 move variable to final
2280         private AdapterService mService;
2281 
AdapterServiceBinder(AdapterService svc)2282         AdapterServiceBinder(AdapterService svc) {
2283             mService = svc;
2284             mService.invalidateBluetoothGetStateCache();
2285             BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache();
2286         }
2287 
cleanup()2288         public void cleanup() {
2289             mService = null;
2290         }
2291 
getService()2292         public AdapterService getService() {
2293             if (mService != null && mService.isAvailable()) {
2294                 return mService;
2295             }
2296             return null;
2297         }
2298 
2299         @Override
getState()2300         public int getState() {
2301             AdapterService service = getService();
2302             if (service == null) {
2303                 return BluetoothAdapter.STATE_OFF;
2304             }
2305 
2306             return service.getState();
2307         }
2308 
2309         @Override
killBluetoothProcess()2310         public void killBluetoothProcess() {
2311             mService.enforceCallingPermission(
2312                     android.Manifest.permission.BLUETOOTH_PRIVILEGED, null);
2313 
2314             Runnable killAction =
2315                     () -> {
2316                         if (Flags.killInsteadOfExit()) {
2317                             Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())");
2318                             Process.killProcess(Process.myPid());
2319                         } else {
2320                             Log.i(TAG, "killBluetoothProcess: Calling System.exit");
2321                             System.exit(0);
2322                         }
2323                     };
2324 
2325             // Post on the main handler to let the cleanup complete before calling exit
2326             mService.mHandler.post(killAction);
2327 
2328             try {
2329                 // Wait for Bluetooth to be killed from its main thread
2330                 Thread.sleep(950); // SystemServer is waiting 1000 ms, we need to wait less here
2331             } catch (InterruptedException e) {
2332                 Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill");
2333             }
2334 
2335             // Bluetooth cannot be killed on the main thread; it is in a deadLock.
2336             // Trying to recover by killing the Bluetooth from the binder thread.
2337             // This is bad :(
2338             Counter.logIncrement("bluetooth.value_kill_from_binder_thread");
2339             Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder");
2340             killAction.run();
2341         }
2342 
2343         @Override
enable(boolean quietMode, AttributionSource attributionSource)2344         public void enable(boolean quietMode, AttributionSource attributionSource) {
2345             AdapterService service = getService();
2346             if (service == null
2347                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "enable")
2348                     || !Utils.checkConnectPermissionForDataDelivery(
2349                             service, attributionSource, "AdapterService enable")) {
2350                 return;
2351             }
2352 
2353             service.enable(quietMode);
2354         }
2355 
2356         @Override
disable(AttributionSource attributionSource)2357         public void disable(AttributionSource attributionSource) {
2358             AdapterService service = getService();
2359             if (service == null
2360                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "disable")
2361                     || !Utils.checkConnectPermissionForDataDelivery(
2362                             service, attributionSource, "AdapterService disable")) {
2363                 return;
2364             }
2365 
2366             service.disable();
2367         }
2368 
2369         @Override
getAddress(AttributionSource attributionSource)2370         public String getAddress(AttributionSource attributionSource) {
2371             AdapterService service = getService();
2372             if (service == null
2373                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress")
2374                     || !Utils.checkConnectPermissionForDataDelivery(
2375                             service, attributionSource, "AdapterService getAddress")) {
2376                 return null;
2377             }
2378 
2379             enforceLocalMacAddressPermission(service);
2380 
2381             return Utils.getAddressStringFromByte(service.mAdapterProperties.getAddress());
2382         }
2383 
2384         @Override
isLogRedactionEnabled()2385         public boolean isLogRedactionEnabled() {
2386             AdapterService service = getService();
2387             if (service == null) {
2388                 return true;
2389             }
2390             return service.mNativeInterface.isLogRedactionEnabled();
2391         }
2392 
2393         @Override
getUuids(AttributionSource attributionSource)2394         public List<ParcelUuid> getUuids(AttributionSource attributionSource) {
2395             AdapterService service = getService();
2396             if (service == null
2397                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids")
2398                     || !Utils.checkConnectPermissionForDataDelivery(
2399                             service, attributionSource, "AdapterService getUuids")) {
2400                 return Collections.emptyList();
2401             }
2402 
2403             ParcelUuid[] parcels = service.mAdapterProperties.getUuids();
2404             if (parcels == null) {
2405                 parcels = new ParcelUuid[0];
2406             }
2407             return Arrays.asList(parcels);
2408         }
2409 
2410         @Override
getIdentityAddress(String address)2411         public String getIdentityAddress(String address) {
2412             AdapterService service = getService();
2413             if (service == null
2414                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress")
2415                     || !Utils.checkConnectPermissionForDataDelivery(
2416                             service,
2417                             Utils.getCallingAttributionSource(mService),
2418                             "AdapterService getIdentityAddress")) {
2419                 return null;
2420             }
2421             enforceBluetoothPrivilegedPermission(service);
2422             return service.getIdentityAddress(address);
2423         }
2424 
2425         @Override
getName(AttributionSource attributionSource)2426         public String getName(AttributionSource attributionSource) {
2427             AdapterService service = getService();
2428             if (service == null
2429                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName")
2430                     || !Utils.checkConnectPermissionForDataDelivery(
2431                             service, attributionSource, "AdapterService getName")) {
2432                 return null;
2433             }
2434 
2435             return service.getName();
2436         }
2437 
2438         @Override
getNameLengthForAdvertise(AttributionSource attributionSource)2439         public int getNameLengthForAdvertise(AttributionSource attributionSource) {
2440             AdapterService service = getService();
2441             if (service == null
2442                     || !callerIsSystemOrActiveOrManagedUser(
2443                             service, TAG, "getNameLengthForAdvertise")
2444                     || !Utils.checkAdvertisePermissionForDataDelivery(
2445                             service, attributionSource, TAG)) {
2446                 return -1;
2447             }
2448 
2449             return service.getNameLengthForAdvertise();
2450         }
2451 
2452         @Override
setName(String name, AttributionSource attributionSource)2453         public boolean setName(String name, AttributionSource attributionSource) {
2454             AdapterService service = getService();
2455             if (service == null
2456                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName")
2457                     || !Utils.checkConnectPermissionForDataDelivery(
2458                             service, attributionSource, "AdapterService setName")) {
2459                 return false;
2460             }
2461 
2462             Log.d(TAG, "AdapterServiceBinder.setName(" + name + ")");
2463             return service.mAdapterProperties.setName(name);
2464         }
2465 
2466         @Override
getScanMode(AttributionSource attributionSource)2467         public int getScanMode(AttributionSource attributionSource) {
2468             AdapterService service = getService();
2469             if (service == null
2470                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode")
2471                     || !Utils.checkScanPermissionForDataDelivery(
2472                             service, attributionSource, "AdapterService getScanMode")) {
2473                 return BluetoothAdapter.SCAN_MODE_NONE;
2474             }
2475 
2476             return service.getScanMode();
2477         }
2478 
2479         @Override
setScanMode(int mode, AttributionSource attributionSource)2480         public int setScanMode(int mode, AttributionSource attributionSource) {
2481             AdapterService service = getService();
2482             if (service == null
2483                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode")
2484                     || !Utils.checkScanPermissionForDataDelivery(
2485                             service, attributionSource, "AdapterService setScanMode")) {
2486                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
2487             }
2488             enforceBluetoothPrivilegedPermission(service);
2489 
2490             return service.mAdapterProperties.setScanMode(mode)
2491                     ? BluetoothStatusCodes.SUCCESS
2492                     : BluetoothStatusCodes.ERROR_UNKNOWN;
2493         }
2494 
2495         @Override
getDiscoverableTimeout(AttributionSource attributionSource)2496         public long getDiscoverableTimeout(AttributionSource attributionSource) {
2497             AdapterService service = getService();
2498             if (service == null
2499                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout")
2500                     || !Utils.checkScanPermissionForDataDelivery(
2501                             service, attributionSource, "AdapterService getDiscoverableTimeout")) {
2502                 return -1;
2503             }
2504 
2505             return service.mAdapterProperties.getDiscoverableTimeout();
2506         }
2507 
2508         @Override
setDiscoverableTimeout(long timeout, AttributionSource attributionSource)2509         public int setDiscoverableTimeout(long timeout, AttributionSource attributionSource) {
2510             AdapterService service = getService();
2511             if (service == null
2512                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout")
2513                     || !Utils.checkScanPermissionForDataDelivery(
2514                             service, attributionSource, "AdapterService setDiscoverableTimeout")) {
2515                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
2516             }
2517             enforceBluetoothPrivilegedPermission(service);
2518 
2519             return service.mAdapterProperties.setDiscoverableTimeout((int) timeout)
2520                     ? BluetoothStatusCodes.SUCCESS
2521                     : BluetoothStatusCodes.ERROR_UNKNOWN;
2522         }
2523 
2524         @Override
startDiscovery(AttributionSource attributionSource)2525         public boolean startDiscovery(AttributionSource attributionSource) {
2526             AdapterService service = getService();
2527             if (service == null
2528                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")) {
2529                 return false;
2530             }
2531 
2532             if (!Utils.checkScanPermissionForDataDelivery(
2533                     service, attributionSource, "Starting discovery.")) {
2534                 return false;
2535             }
2536 
2537             Log.i(TAG, "startDiscovery: from " + Utils.getUidPidString());
2538             return service.startDiscovery(attributionSource);
2539         }
2540 
2541         @Override
cancelDiscovery(AttributionSource attributionSource)2542         public boolean cancelDiscovery(AttributionSource attributionSource) {
2543             AdapterService service = getService();
2544             if (service == null
2545                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery")
2546                     || !Utils.checkScanPermissionForDataDelivery(
2547                             service, attributionSource, "AdapterService cancelDiscovery")) {
2548                 return false;
2549             }
2550 
2551             Log.i(TAG, "cancelDiscovery: from " + Utils.getUidPidString());
2552             return service.mNativeInterface.cancelDiscovery();
2553         }
2554 
2555         @Override
isDiscovering(AttributionSource attributionSource)2556         public boolean isDiscovering(AttributionSource attributionSource) {
2557             AdapterService service = getService();
2558             if (service == null
2559                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering")
2560                     || !Utils.checkScanPermissionForDataDelivery(
2561                             service, attributionSource, "AdapterService isDiscovering")) {
2562                 return false;
2563             }
2564 
2565             return service.mAdapterProperties.isDiscovering();
2566         }
2567 
2568         @Override
getDiscoveryEndMillis(AttributionSource source)2569         public long getDiscoveryEndMillis(AttributionSource source) {
2570             AdapterService service = getService();
2571             if (service == null
2572                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis")
2573                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2574                 return -1;
2575             }
2576 
2577             enforceBluetoothPrivilegedPermission(service);
2578 
2579             return service.mAdapterProperties.discoveryEndMillis();
2580         }
2581 
2582         @Override
getMostRecentlyConnectedDevices( AttributionSource attributionSource)2583         public List<BluetoothDevice> getMostRecentlyConnectedDevices(
2584                 AttributionSource attributionSource) {
2585             // don't check caller, may be called from system UI
2586             AdapterService service = getService();
2587             if (service == null
2588                     || !Utils.checkConnectPermissionForDataDelivery(
2589                             service,
2590                             attributionSource,
2591                             "AdapterService getMostRecentlyConnectedDevices")) {
2592                 return Collections.emptyList();
2593             }
2594 
2595             enforceBluetoothPrivilegedPermission(service);
2596 
2597             return service.mDatabaseManager.getMostRecentlyConnectedDevices();
2598         }
2599 
2600         @Override
getBondedDevices(AttributionSource attributionSource)2601         public List<BluetoothDevice> getBondedDevices(AttributionSource attributionSource) {
2602             // don't check caller, may be called from system UI
2603             AdapterService service = getService();
2604             if (service == null
2605                     || !Utils.checkConnectPermissionForDataDelivery(
2606                             service, attributionSource, "AdapterService getBondedDevices")) {
2607                 return Collections.emptyList();
2608             }
2609 
2610             return Arrays.asList(service.getBondedDevices());
2611         }
2612 
2613         @Override
getAdapterConnectionState()2614         public int getAdapterConnectionState() {
2615             // don't check caller, may be called from system UI
2616             AdapterService service = getService();
2617             if (service == null) {
2618                 return BluetoothAdapter.STATE_DISCONNECTED;
2619             }
2620 
2621             return service.mAdapterProperties.getConnectionState();
2622         }
2623 
2624         /**
2625          * This method has an associated binder cache. The invalidation methods must be changed if
2626          * the logic behind this method changes.
2627          */
2628         @Override
getProfileConnectionState(int profile, AttributionSource source)2629         public int getProfileConnectionState(int profile, AttributionSource source) {
2630             AdapterService service = getService();
2631             boolean checkConnect = false;
2632             final int callingUid = Binder.getCallingUid();
2633             final long token = Binder.clearCallingIdentity();
2634             try {
2635                 checkConnect = CompatChanges.isChangeEnabled(ENFORCE_CONNECT, callingUid);
2636             } finally {
2637                 Binder.restoreCallingIdentity(token);
2638             }
2639             if (service == null
2640                     || !callerIsSystemOrActiveOrManagedUser(
2641                             service, TAG, "getProfileConnectionState")
2642                     || (checkConnect
2643                             && !Utils.checkConnectPermissionForDataDelivery(
2644                                     service, source, "AdapterService getProfileConnectionState"))) {
2645                 return BluetoothProfile.STATE_DISCONNECTED;
2646             }
2647 
2648             return service.mAdapterProperties.getProfileConnectionState(profile);
2649         }
2650 
2651         @Override
createBond( BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, AttributionSource attributionSource)2652         public boolean createBond(
2653                 BluetoothDevice device,
2654                 int transport,
2655                 OobData remoteP192Data,
2656                 OobData remoteP256Data,
2657                 AttributionSource attributionSource) {
2658             AdapterService service = getService();
2659             if (service == null
2660                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")
2661                     || !Utils.checkConnectPermissionForDataDelivery(
2662                             service, attributionSource, "AdapterService createBond")) {
2663                 return false;
2664             }
2665 
2666             // This conditional is required to satisfy permission dependencies
2667             // since createBond calls createBondOutOfBand with null value passed as data.
2668             // BluetoothDevice#createBond requires BLUETOOTH_ADMIN only.
2669             service.enforceBluetoothPrivilegedPermissionIfNeeded(remoteP192Data, remoteP256Data);
2670 
2671             Log.i(
2672                     TAG,
2673                     "createBond: device="
2674                             + device
2675                             + ", transport="
2676                             + transport
2677                             + ", from "
2678                             + Utils.getUidPidString());
2679             return service.createBond(
2680                     device,
2681                     transport,
2682                     remoteP192Data,
2683                     remoteP256Data,
2684                     attributionSource.getPackageName());
2685         }
2686 
2687         @Override
cancelBondProcess( BluetoothDevice device, AttributionSource attributionSource)2688         public boolean cancelBondProcess(
2689                 BluetoothDevice device, AttributionSource attributionSource) {
2690             AdapterService service = getService();
2691             if (service == null
2692                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess")
2693                     || !Utils.checkConnectPermissionForDataDelivery(
2694                             service, attributionSource, "AdapterService cancelBondProcess")) {
2695                 return false;
2696             }
2697 
2698             enforceBluetoothPrivilegedPermission(service);
2699 
2700             Log.i(TAG, "cancelBondProcess: device=" + device + ", from " + Utils.getUidPidString());
2701 
2702             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
2703             if (deviceProp != null) {
2704                 deviceProp.setBondingInitiatedLocally(false);
2705             }
2706 
2707             return service.mNativeInterface.cancelBond(getBytesFromAddress(device.getAddress()));
2708         }
2709 
2710         @Override
removeBond(BluetoothDevice device, AttributionSource attributionSource)2711         public boolean removeBond(BluetoothDevice device, AttributionSource attributionSource) {
2712             AdapterService service = getService();
2713             if (service == null
2714                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond")
2715                     || !Utils.checkConnectPermissionForDataDelivery(
2716                             service, attributionSource, "AdapterService removeBond")) {
2717                 return false;
2718             }
2719 
2720             Log.i(TAG, "removeBond: device=" + device + ", from " + Utils.getUidPidString());
2721 
2722             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
2723             if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
2724                 Log.w(
2725                         TAG,
2726                         device.getAddressForLogging()
2727                                 + " cannot be removed since "
2728                                 + ((deviceProp == null)
2729                                         ? "properties are empty"
2730                                         : "bond state is " + deviceProp.getBondState()));
2731                 return false;
2732             }
2733             service.mBondAttemptCallerInfo.remove(device.getAddress());
2734             deviceProp.setBondingInitiatedLocally(false);
2735 
2736             Message msg = service.mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
2737             msg.obj = device;
2738             service.mBondStateMachine.sendMessage(msg);
2739             return true;
2740         }
2741 
2742         @Override
getBondState(BluetoothDevice device, AttributionSource attributionSource)2743         public int getBondState(BluetoothDevice device, AttributionSource attributionSource) {
2744             // don't check caller, may be called from system UI
2745             AdapterService service = getService();
2746             if (service == null
2747                     || !Utils.checkConnectPermissionForDataDelivery(
2748                             service, attributionSource, "AdapterService getBondState")) {
2749                 return BluetoothDevice.BOND_NONE;
2750             }
2751 
2752             return service.getBondState(device);
2753         }
2754 
2755         @Override
isBondingInitiatedLocally( BluetoothDevice device, AttributionSource attributionSource)2756         public boolean isBondingInitiatedLocally(
2757                 BluetoothDevice device, AttributionSource attributionSource) {
2758             // don't check caller, may be called from system UI
2759             AdapterService service = getService();
2760             if (service == null
2761                     || !Utils.checkConnectPermissionForDataDelivery(
2762                             service,
2763                             attributionSource,
2764                             "AdapterService isBondingInitiatedLocally")) {
2765                 return false;
2766             }
2767 
2768             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
2769             return deviceProp != null && deviceProp.isBondingInitiatedLocally();
2770         }
2771 
2772         @Override
generateLocalOobData( int transport, IBluetoothOobDataCallback callback, AttributionSource source)2773         public void generateLocalOobData(
2774                 int transport, IBluetoothOobDataCallback callback, AttributionSource source) {
2775             AdapterService service = getService();
2776             if (service == null
2777                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData")
2778                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2779                 return;
2780             }
2781             enforceBluetoothPrivilegedPermission(service);
2782             service.generateLocalOobData(transport, callback);
2783         }
2784 
2785         @Override
getSupportedProfiles(AttributionSource source)2786         public long getSupportedProfiles(AttributionSource source) {
2787             AdapterService service = getService();
2788             if (service == null
2789                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2790                 return 0;
2791             }
2792             enforceBluetoothPrivilegedPermission(service);
2793 
2794             return Config.getSupportedProfilesBitMask();
2795         }
2796 
2797         @Override
getConnectionState(BluetoothDevice device, AttributionSource attributionSource)2798         public int getConnectionState(BluetoothDevice device, AttributionSource attributionSource) {
2799             AdapterService service = getService();
2800             if (service == null
2801                     || !Utils.checkConnectPermissionForDataDelivery(
2802                             service, attributionSource, "AdapterService getConnectionState")) {
2803                 return BluetoothDevice.CONNECTION_STATE_DISCONNECTED;
2804             }
2805 
2806             return service.getConnectionState(device);
2807         }
2808 
2809         @Override
getConnectionHandle( BluetoothDevice device, int transport, AttributionSource attributionSource)2810         public int getConnectionHandle(
2811                 BluetoothDevice device, int transport, AttributionSource attributionSource) {
2812             AdapterService service = getService();
2813             if (service == null
2814                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getConnectionHandle")
2815                     || !Utils.checkConnectPermissionForDataDelivery(
2816                             service, attributionSource, TAG)) {
2817                 return BluetoothDevice.ERROR;
2818             }
2819 
2820             enforceBluetoothPrivilegedPermission(service);
2821 
2822             return service.getConnectionHandle(device, transport);
2823         }
2824 
2825         @Override
canBondWithoutDialog(BluetoothDevice device, AttributionSource source)2826         public boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) {
2827             AdapterService service = getService();
2828             if (service == null
2829                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2830                 return false;
2831             }
2832 
2833             enforceBluetoothPrivilegedPermission(service);
2834 
2835             return service.canBondWithoutDialog(device);
2836         }
2837 
2838         @Override
getPackageNameOfBondingApplication(BluetoothDevice device)2839         public String getPackageNameOfBondingApplication(BluetoothDevice device) {
2840             AdapterService service = getService();
2841 
2842             if (service == null) {
2843                 return null;
2844             }
2845 
2846             enforceBluetoothPrivilegedPermission(service);
2847 
2848             return service.getPackageNameOfBondingApplication(device);
2849         }
2850 
2851         @Override
removeActiveDevice(@ctiveDeviceUse int profiles, AttributionSource source)2852         public boolean removeActiveDevice(@ActiveDeviceUse int profiles, AttributionSource source) {
2853             AdapterService service = getService();
2854             if (service == null
2855                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice")
2856                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2857                 return false;
2858             }
2859             Log.i(
2860                     TAG,
2861                     "removeActiveDevice: profiles="
2862                             + profiles
2863                             + ", from "
2864                             + Utils.getUidPidString());
2865             return service.setActiveDevice(null, profiles);
2866         }
2867 
2868         @Override
setActiveDevice( BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source)2869         public boolean setActiveDevice(
2870                 BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source) {
2871             AdapterService service = getService();
2872             if (service == null
2873                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice")
2874                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2875                 return false;
2876             }
2877 
2878             enforceBluetoothPrivilegedPermission(service);
2879 
2880             Log.i(
2881                     TAG,
2882                     "setActiveDevice: device="
2883                             + device
2884                             + ", profiles="
2885                             + profiles
2886                             + ", from "
2887                             + Utils.getUidPidString());
2888 
2889             return service.setActiveDevice(device, profiles);
2890         }
2891 
2892         @Override
getActiveDevices( @ctiveDeviceProfile int profile, AttributionSource source)2893         public List<BluetoothDevice> getActiveDevices(
2894                 @ActiveDeviceProfile int profile, AttributionSource source) {
2895             AdapterService service = getService();
2896             if (service == null
2897                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices")
2898                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2899                 return Collections.emptyList();
2900             }
2901 
2902             enforceBluetoothPrivilegedPermission(service);
2903 
2904             return service.getActiveDevices(profile);
2905         }
2906 
2907         @Override
connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source)2908         public int connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) {
2909             AdapterService service = getService();
2910             if (service == null) {
2911                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
2912             }
2913             if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) {
2914                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
2915             }
2916             if (device == null) {
2917                 throw new IllegalArgumentException("device cannot be null");
2918             }
2919             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
2920                 throw new IllegalArgumentException("device cannot have an invalid address");
2921             }
2922             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2923                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
2924             }
2925 
2926             enforceBluetoothPrivilegedPermission(service);
2927 
2928             Log.i(
2929                     TAG,
2930                     "connectAllEnabledProfiles: device="
2931                             + device
2932                             + ", from "
2933                             + Utils.getUidPidString());
2934 
2935             try {
2936                 return service.connectAllEnabledProfiles(device);
2937             } catch (Exception e) {
2938                 Log.v(TAG, "connectAllEnabledProfiles() failed", e);
2939                 SneakyThrow.sneakyThrow(e);
2940                 throw new RuntimeException(e);
2941             }
2942         }
2943 
2944         @Override
disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source)2945         public int disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) {
2946             AdapterService service = getService();
2947             if (service == null) {
2948                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
2949             }
2950             if (!callerIsSystemOrActiveOrManagedUser(
2951                     service, TAG, "disconnectAllEnabledProfiles")) {
2952                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
2953             }
2954             if (device == null) {
2955                 throw new IllegalArgumentException("device cannot be null");
2956             }
2957             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
2958                 throw new IllegalArgumentException("device cannot have an invalid address");
2959             }
2960             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
2961                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
2962             }
2963 
2964             enforceBluetoothPrivilegedPermission(service);
2965 
2966             Log.i(
2967                     TAG,
2968                     "disconnectAllEnabledProfiles: device="
2969                             + device
2970                             + ", from "
2971                             + Utils.getUidPidString());
2972 
2973             try {
2974                 return service.disconnectAllEnabledProfiles(device);
2975             } catch (Exception e) {
2976                 Log.v(TAG, "disconnectAllEnabledProfiles() failed", e);
2977                 SneakyThrow.sneakyThrow(e);
2978                 throw new RuntimeException(e);
2979             }
2980         }
2981 
2982         @Override
getRemoteName(BluetoothDevice device, AttributionSource attributionSource)2983         public String getRemoteName(BluetoothDevice device, AttributionSource attributionSource) {
2984             AdapterService service = getService();
2985             if (service == null
2986                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName")
2987                     || !Utils.checkConnectPermissionForDataDelivery(
2988                             service, attributionSource, "AdapterService getRemoteName")) {
2989                 return null;
2990             }
2991 
2992             return service.getRemoteName(device);
2993         }
2994 
2995         @Override
getRemoteType(BluetoothDevice device, AttributionSource attributionSource)2996         public int getRemoteType(BluetoothDevice device, AttributionSource attributionSource) {
2997             AdapterService service = getService();
2998             if (service == null
2999                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType")
3000                     || !Utils.checkConnectPermissionForDataDelivery(
3001                             service, attributionSource, "AdapterService getRemoteType")) {
3002                 return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
3003             }
3004 
3005             return service.getRemoteType(device);
3006         }
3007 
3008         @Override
getRemoteAlias(BluetoothDevice device, AttributionSource attributionSource)3009         public String getRemoteAlias(BluetoothDevice device, AttributionSource attributionSource) {
3010             AdapterService service = getService();
3011             if (service == null
3012                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias")
3013                     || !Utils.checkConnectPermissionForDataDelivery(
3014                             service, attributionSource, "AdapterService getRemoteAlias")) {
3015                 return null;
3016             }
3017 
3018             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3019             return deviceProp != null ? deviceProp.getAlias() : null;
3020         }
3021 
3022         @Override
setRemoteAlias( BluetoothDevice device, String name, AttributionSource attributionSource)3023         public int setRemoteAlias(
3024                 BluetoothDevice device, String name, AttributionSource attributionSource) {
3025             AdapterService service = getService();
3026             if (service == null) {
3027                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3028             }
3029             if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) {
3030                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
3031             }
3032             if (name != null && name.isEmpty()) {
3033                 throw new IllegalArgumentException("alias cannot be the empty string");
3034             }
3035 
3036             if (!hasBluetoothPrivilegedPermission(service)) {
3037                 if (!Utils.checkConnectPermissionForDataDelivery(
3038                         service, attributionSource, "AdapterService setRemoteAlias")) {
3039                     return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
3040                 }
3041                 enforceCdmAssociation(
3042                         service.mCompanionDeviceManager,
3043                         service,
3044                         attributionSource.getPackageName(),
3045                         Binder.getCallingUid(),
3046                         device);
3047             }
3048 
3049             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3050             if (deviceProp == null) {
3051                 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
3052             }
3053             deviceProp.setAlias(device, name);
3054             return BluetoothStatusCodes.SUCCESS;
3055         }
3056 
3057         @Override
getRemoteClass(BluetoothDevice device, AttributionSource attributionSource)3058         public int getRemoteClass(BluetoothDevice device, AttributionSource attributionSource) {
3059             AdapterService service = getService();
3060             if (service == null
3061                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass")
3062                     || !Utils.checkConnectPermissionForDataDelivery(
3063                             service, attributionSource, "AdapterService getRemoteClass")) {
3064                 return 0;
3065             }
3066 
3067             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3068             return deviceProp != null ? deviceProp.getBluetoothClass() : 0;
3069         }
3070 
3071         @Override
getRemoteUuids( BluetoothDevice device, AttributionSource attributionSource)3072         public List<ParcelUuid> getRemoteUuids(
3073                 BluetoothDevice device, AttributionSource attributionSource) {
3074             AdapterService service = getService();
3075             if (service == null
3076                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids")
3077                     || !Utils.checkConnectPermissionForDataDelivery(
3078                             service, attributionSource, "AdapterService getRemoteUuids")) {
3079                 return Collections.emptyList();
3080             }
3081 
3082             ParcelUuid[] parcels = service.getRemoteUuids(device);
3083             if (parcels == null) {
3084                 return null;
3085             }
3086             return Arrays.asList(parcels);
3087         }
3088 
3089         @Override
fetchRemoteUuids( BluetoothDevice device, int transport, AttributionSource attributionSource)3090         public boolean fetchRemoteUuids(
3091                 BluetoothDevice device, int transport, AttributionSource attributionSource) {
3092             AdapterService service = getService();
3093             if (service == null
3094                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids")
3095                     || !Utils.checkConnectPermissionForDataDelivery(
3096                             service, attributionSource, "AdapterService fetchRemoteUuids")) {
3097                 return false;
3098             }
3099             if (transport != TRANSPORT_AUTO) {
3100                 enforceBluetoothPrivilegedPermission(service);
3101             }
3102 
3103             Log.i(
3104                     TAG,
3105                     "fetchRemoteUuids: device="
3106                             + device
3107                             + ", transport="
3108                             + transport
3109                             + ", from "
3110                             + Utils.getUidPidString());
3111 
3112             service.mRemoteDevices.fetchUuids(device, transport);
3113             MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_FETCH_UUID_REQUEST, 1);
3114             return true;
3115         }
3116 
3117         @Override
setPin( BluetoothDevice device, boolean accept, int len, byte[] pinCode, AttributionSource attributionSource)3118         public boolean setPin(
3119                 BluetoothDevice device,
3120                 boolean accept,
3121                 int len,
3122                 byte[] pinCode,
3123                 AttributionSource attributionSource) {
3124             AdapterService service = getService();
3125             if (service == null
3126                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin")
3127                     || !Utils.checkConnectPermissionForDataDelivery(
3128                             service, attributionSource, "AdapterService setPin")) {
3129                 return false;
3130             }
3131 
3132             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3133             // Only allow setting a pin in bonding state, or bonded state in case of security
3134             // upgrade.
3135             if (deviceProp == null || !deviceProp.isBondingOrBonded()) {
3136                 Log.e(TAG, "setPin: device=" + device + ", not bonding");
3137                 return false;
3138             }
3139             if (pinCode.length != len) {
3140                 android.util.EventLog.writeEvent(
3141                         0x534e4554, "139287605", -1, "PIN code length mismatch");
3142                 return false;
3143             }
3144             service.logUserBondResponse(
3145                     device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_PIN_REPLIED);
3146             Log.i(
3147                     TAG,
3148                     "setPin: device="
3149                             + device
3150                             + ", accept="
3151                             + accept
3152                             + ", from "
3153                             + Utils.getUidPidString());
3154             return service.mNativeInterface.pinReply(
3155                     getBytesFromAddress(device.getAddress()), accept, len, pinCode);
3156         }
3157 
3158         @Override
setPasskey( BluetoothDevice device, boolean accept, int len, byte[] passkey, AttributionSource attributionSource)3159         public boolean setPasskey(
3160                 BluetoothDevice device,
3161                 boolean accept,
3162                 int len,
3163                 byte[] passkey,
3164                 AttributionSource attributionSource) {
3165             AdapterService service = getService();
3166             if (service == null
3167                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey")
3168                     || !Utils.checkConnectPermissionForDataDelivery(
3169                             service, attributionSource, "AdapterService setPasskey")) {
3170                 return false;
3171             }
3172 
3173             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3174             if (deviceProp == null || !deviceProp.isBonding()) {
3175                 Log.e(TAG, "setPasskey: device=" + device + ", not bonding");
3176                 return false;
3177             }
3178             if (passkey.length != len) {
3179                 android.util.EventLog.writeEvent(
3180                         0x534e4554, "139287605", -1, "Passkey length mismatch");
3181                 return false;
3182             }
3183             service.logUserBondResponse(
3184                     device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_SSP_REPLIED);
3185             Log.i(
3186                     TAG,
3187                     "setPasskey: device="
3188                             + device
3189                             + ", accept="
3190                             + accept
3191                             + ", from "
3192                             + Utils.getUidPidString());
3193 
3194             return service.mNativeInterface.sspReply(
3195                     getBytesFromAddress(device.getAddress()),
3196                     AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY,
3197                     accept,
3198                     Utils.byteArrayToInt(passkey));
3199         }
3200 
3201         @Override
setPairingConfirmation( BluetoothDevice device, boolean accept, AttributionSource source)3202         public boolean setPairingConfirmation(
3203                 BluetoothDevice device, boolean accept, AttributionSource source) {
3204             AdapterService service = getService();
3205             if (service == null
3206                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation")
3207                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3208                 return false;
3209             }
3210 
3211             enforceBluetoothPrivilegedPermission(service);
3212 
3213             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3214             if (deviceProp == null || !deviceProp.isBonding()) {
3215                 Log.e(TAG, "setPairingConfirmation: device=" + device + ", not bonding");
3216                 return false;
3217             }
3218             service.logUserBondResponse(
3219                     device, accept, BluetoothProtoEnums.BOND_SUB_STATE_LOCAL_SSP_REPLIED);
3220             Log.i(
3221                     TAG,
3222                     "setPairingConfirmation: device="
3223                             + device
3224                             + ", accept="
3225                             + accept
3226                             + ", from "
3227                             + Utils.getUidPidString());
3228 
3229             return service.mNativeInterface.sspReply(
3230                     getBytesFromAddress(device.getAddress()),
3231                     AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
3232                     accept,
3233                     0);
3234         }
3235 
3236         @Override
getSilenceMode(BluetoothDevice device, AttributionSource source)3237         public boolean getSilenceMode(BluetoothDevice device, AttributionSource source) {
3238             AdapterService service = getService();
3239             if (service == null
3240                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode")
3241                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3242                 return false;
3243             }
3244 
3245             enforceBluetoothPrivilegedPermission(service);
3246 
3247             return service.mSilenceDeviceManager.getSilenceMode(device);
3248         }
3249 
3250         @Override
setSilenceMode( BluetoothDevice device, boolean silence, AttributionSource source)3251         public boolean setSilenceMode(
3252                 BluetoothDevice device, boolean silence, AttributionSource source) {
3253             AdapterService service = getService();
3254             if (service == null
3255                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode")
3256                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3257                 return false;
3258             }
3259 
3260             enforceBluetoothPrivilegedPermission(service);
3261 
3262             service.mSilenceDeviceManager.setSilenceMode(device, silence);
3263             return true;
3264         }
3265 
3266         @Override
getPhonebookAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3267         public int getPhonebookAccessPermission(
3268                 BluetoothDevice device, AttributionSource attributionSource) {
3269             AdapterService service = getService();
3270             if (service == null
3271                     || !callerIsSystemOrActiveOrManagedUser(
3272                             service, TAG, "getPhonebookAccessPermission")
3273                     || !Utils.checkConnectPermissionForDataDelivery(
3274                             service,
3275                             attributionSource,
3276                             "AdapterService getPhonebookAccessPermission")) {
3277                 return BluetoothDevice.ACCESS_UNKNOWN;
3278             }
3279 
3280             return service.getDeviceAccessFromPrefs(
3281                     device, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE);
3282         }
3283 
3284         @Override
setPhonebookAccessPermission( BluetoothDevice device, int value, AttributionSource source)3285         public boolean setPhonebookAccessPermission(
3286                 BluetoothDevice device, int value, AttributionSource source) {
3287             AdapterService service = getService();
3288             if (service == null
3289                     || !callerIsSystemOrActiveOrManagedUser(
3290                             service, TAG, "setPhonebookAccessPermission")
3291                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3292                 return false;
3293             }
3294 
3295             enforceBluetoothPrivilegedPermission(service);
3296 
3297             service.setPhonebookAccessPermission(device, value);
3298             return true;
3299         }
3300 
3301         @Override
getMessageAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3302         public int getMessageAccessPermission(
3303                 BluetoothDevice device, AttributionSource attributionSource) {
3304             AdapterService service = getService();
3305             if (service == null
3306                     || !callerIsSystemOrActiveOrManagedUser(
3307                             service, TAG, "getMessageAccessPermission")
3308                     || !Utils.checkConnectPermissionForDataDelivery(
3309                             service,
3310                             attributionSource,
3311                             "AdapterService getMessageAccessPermission")) {
3312                 return BluetoothDevice.ACCESS_UNKNOWN;
3313             }
3314 
3315             return service.getDeviceAccessFromPrefs(
3316                     device, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE);
3317         }
3318 
3319         @Override
setMessageAccessPermission( BluetoothDevice device, int value, AttributionSource source)3320         public boolean setMessageAccessPermission(
3321                 BluetoothDevice device, int value, AttributionSource source) {
3322             AdapterService service = getService();
3323             if (service == null
3324                     || !callerIsSystemOrActiveOrManagedUser(
3325                             service, TAG, "setMessageAccessPermission")
3326                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3327                 return false;
3328             }
3329 
3330             enforceBluetoothPrivilegedPermission(service);
3331 
3332             service.setMessageAccessPermission(device, value);
3333             return true;
3334         }
3335 
3336         @Override
getSimAccessPermission( BluetoothDevice device, AttributionSource attributionSource)3337         public int getSimAccessPermission(
3338                 BluetoothDevice device, AttributionSource attributionSource) {
3339             AdapterService service = getService();
3340             if (service == null
3341                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSimAccessPermission")
3342                     || !Utils.checkConnectPermissionForDataDelivery(
3343                             service, attributionSource, "AdapterService getSimAccessPermission")) {
3344                 return BluetoothDevice.ACCESS_UNKNOWN;
3345             }
3346 
3347             return service.getDeviceAccessFromPrefs(device, SIM_ACCESS_PERMISSION_PREFERENCE_FILE);
3348         }
3349 
3350         @Override
setSimAccessPermission( BluetoothDevice device, int value, AttributionSource source)3351         public boolean setSimAccessPermission(
3352                 BluetoothDevice device, int value, AttributionSource source) {
3353             AdapterService service = getService();
3354             if (service == null
3355                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission")
3356                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3357                 return false;
3358             }
3359 
3360             enforceBluetoothPrivilegedPermission(service);
3361 
3362             service.setSimAccessPermission(device, value);
3363             return true;
3364         }
3365 
3366         @Override
logL2capcocServerConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis, long timeoutMillis)3367         public void logL2capcocServerConnection(
3368                 BluetoothDevice device,
3369                 int port,
3370                 boolean isSecured,
3371                 int result,
3372                 long socketCreationTimeMillis,
3373                 long socketCreationLatencyMillis,
3374                 long socketConnectionTimeMillis,
3375                 long timeoutMillis) {
3376             AdapterService service = getService();
3377             if (service == null) {
3378                 return;
3379             }
3380             service.logL2capcocServerConnection(
3381                     device,
3382                     port,
3383                     isSecured,
3384                     result,
3385                     socketCreationTimeMillis,
3386                     socketCreationLatencyMillis,
3387                     socketConnectionTimeMillis,
3388                     timeoutMillis,
3389                     Binder.getCallingUid());
3390         }
3391 
3392         @Override
getSocketManager()3393         public IBluetoothSocketManager getSocketManager() {
3394             AdapterService service = getService();
3395             if (service == null) {
3396                 return null;
3397             }
3398 
3399             return IBluetoothSocketManager.Stub.asInterface(service.mBluetoothSocketManagerBinder);
3400         }
3401 
3402         @Override
logL2capcocClientConnection( BluetoothDevice device, int port, boolean isSecured, int result, long socketCreationTimeNanos, long socketCreationLatencyNanos, long socketConnectionTimeNanos)3403         public void logL2capcocClientConnection(
3404                 BluetoothDevice device,
3405                 int port,
3406                 boolean isSecured,
3407                 int result,
3408                 long socketCreationTimeNanos,
3409                 long socketCreationLatencyNanos,
3410                 long socketConnectionTimeNanos) {
3411             AdapterService service = getService();
3412             if (service == null) {
3413                 return;
3414             }
3415             service.logL2capcocClientConnection(
3416                     device,
3417                     port,
3418                     isSecured,
3419                     result,
3420                     socketCreationTimeNanos,
3421                     socketCreationLatencyNanos,
3422                     socketConnectionTimeNanos,
3423                     Binder.getCallingUid());
3424         }
3425 
3426         @Override
logRfcommConnectionAttempt( BluetoothDevice device, boolean isSecured, int resultCode, long socketCreationTimeNanos, boolean isSerialPort)3427         public void logRfcommConnectionAttempt(
3428                 BluetoothDevice device,
3429                 boolean isSecured,
3430                 int resultCode,
3431                 long socketCreationTimeNanos,
3432                 boolean isSerialPort) {
3433             AdapterService service = getService();
3434             if (service == null) {
3435                 return;
3436             }
3437             service.logRfcommConnectionAttempt(
3438                     device,
3439                     isSecured,
3440                     resultCode,
3441                     socketCreationTimeNanos,
3442                     isSerialPort,
3443                     Binder.getCallingUid());
3444         }
3445 
3446         @Override
sdpSearch( BluetoothDevice device, ParcelUuid uuid, AttributionSource attributionSource)3447         public boolean sdpSearch(
3448                 BluetoothDevice device, ParcelUuid uuid, AttributionSource attributionSource) {
3449             AdapterService service = getService();
3450             if (service == null
3451                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch")
3452                     || !Utils.checkConnectPermissionForDataDelivery(
3453                             service, attributionSource, "AdapterService sdpSearch")) {
3454                 return false;
3455             }
3456 
3457             if (service.mSdpManager == null) {
3458                 return false;
3459             }
3460             service.mSdpManager.sdpSearch(device, uuid);
3461             return true;
3462         }
3463 
3464         @Override
getBatteryLevel(BluetoothDevice device, AttributionSource attributionSource)3465         public int getBatteryLevel(BluetoothDevice device, AttributionSource attributionSource) {
3466             AdapterService service = getService();
3467             if (service == null
3468                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel")
3469                     || !Utils.checkConnectPermissionForDataDelivery(
3470                             service, attributionSource, "AdapterService getBatteryLevel")) {
3471                 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
3472             }
3473 
3474             DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
3475             if (deviceProp == null) {
3476                 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
3477             }
3478             return deviceProp.getBatteryLevel();
3479         }
3480 
3481         @Override
getMaxConnectedAudioDevices(AttributionSource attributionSource)3482         public int getMaxConnectedAudioDevices(AttributionSource attributionSource) {
3483             // don't check caller, may be called from system UI
3484             AdapterService service = getService();
3485             if (service == null
3486                     || !Utils.checkConnectPermissionForDataDelivery(
3487                             service,
3488                             attributionSource,
3489                             "AdapterService getMaxConnectedAudioDevices")) {
3490                 return -1;
3491             }
3492 
3493             return service.getMaxConnectedAudioDevices();
3494         }
3495 
3496         @Override
factoryReset(AttributionSource source)3497         public boolean factoryReset(AttributionSource source) {
3498             AdapterService service = getService();
3499             if (service == null
3500                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3501                 return false;
3502             }
3503 
3504             enforceBluetoothPrivilegedPermission(service);
3505             return service.factoryReset();
3506         }
3507 
3508         @Override
registerBluetoothConnectionCallback( IBluetoothConnectionCallback callback, AttributionSource source)3509         public void registerBluetoothConnectionCallback(
3510                 IBluetoothConnectionCallback callback, AttributionSource source) {
3511             AdapterService service = getService();
3512             if (service == null
3513                     || !callerIsSystemOrActiveOrManagedUser(
3514                             service, TAG, "registerBluetoothConnectionCallback")
3515                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3516                 return;
3517             }
3518             enforceBluetoothPrivilegedPermission(service);
3519             service.mBluetoothConnectionCallbacks.add(callback);
3520         }
3521 
3522         @Override
unregisterBluetoothConnectionCallback( IBluetoothConnectionCallback callback, AttributionSource source)3523         public void unregisterBluetoothConnectionCallback(
3524                 IBluetoothConnectionCallback callback, AttributionSource source) {
3525             AdapterService service = getService();
3526             if (service == null
3527                     || !callerIsSystemOrActiveOrManagedUser(
3528                             service, TAG, "unregisterBluetoothConnectionCallback")
3529                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3530                 return;
3531             }
3532             enforceBluetoothPrivilegedPermission(service);
3533             service.mBluetoothConnectionCallbacks.remove(callback);
3534         }
3535 
3536         @Override
registerCallback(IBluetoothCallback callback, AttributionSource source)3537         public void registerCallback(IBluetoothCallback callback, AttributionSource source) {
3538             AdapterService service = getService();
3539             if (service == null
3540                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback")
3541                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3542                 return;
3543             }
3544 
3545             enforceBluetoothPrivilegedPermission(service);
3546 
3547             service.registerRemoteCallback(callback);
3548         }
3549 
3550         @Override
unregisterCallback(IBluetoothCallback callback, AttributionSource source)3551         public void unregisterCallback(IBluetoothCallback callback, AttributionSource source) {
3552             AdapterService service = getService();
3553             if (service == null
3554                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback")
3555                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3556                 return;
3557             }
3558 
3559             enforceBluetoothPrivilegedPermission(service);
3560 
3561             service.unregisterRemoteCallback(callback);
3562         }
3563 
3564         @Override
isMultiAdvertisementSupported()3565         public boolean isMultiAdvertisementSupported() {
3566             AdapterService service = getService();
3567             if (service == null) {
3568                 return false;
3569             }
3570 
3571             int val = service.mAdapterProperties.getNumOfAdvertisementInstancesSupported();
3572             return val >= MIN_ADVT_INSTANCES_FOR_MA;
3573         }
3574 
3575         /**
3576          * This method has an associated binder cache. The invalidation methods must be changed if
3577          * the logic behind this method changes.
3578          */
3579         @Override
isOffloadedFilteringSupported()3580         public boolean isOffloadedFilteringSupported() {
3581             AdapterService service = getService();
3582             if (service == null) {
3583                 return false;
3584             }
3585 
3586             int val = service.getNumOfOffloadedScanFilterSupported();
3587             return val >= MIN_OFFLOADED_FILTERS;
3588         }
3589 
3590         @Override
isOffloadedScanBatchingSupported()3591         public boolean isOffloadedScanBatchingSupported() {
3592             AdapterService service = getService();
3593             if (service == null) {
3594                 return false;
3595             }
3596 
3597             int val = service.getOffloadedScanResultStorage();
3598             return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES;
3599         }
3600 
3601         @Override
isLe2MPhySupported()3602         public boolean isLe2MPhySupported() {
3603             AdapterService service = getService();
3604             if (service == null) {
3605                 return false;
3606             }
3607 
3608             return service.isLe2MPhySupported();
3609         }
3610 
3611         @Override
isLeCodedPhySupported()3612         public boolean isLeCodedPhySupported() {
3613             AdapterService service = getService();
3614             if (service == null) {
3615                 return false;
3616             }
3617 
3618             return service.isLeCodedPhySupported();
3619         }
3620 
3621         @Override
isLeExtendedAdvertisingSupported()3622         public boolean isLeExtendedAdvertisingSupported() {
3623             AdapterService service = getService();
3624             if (service == null) {
3625                 return false;
3626             }
3627 
3628             return service.isLeExtendedAdvertisingSupported();
3629         }
3630 
3631         @Override
isLePeriodicAdvertisingSupported()3632         public boolean isLePeriodicAdvertisingSupported() {
3633             AdapterService service = getService();
3634             if (service == null) {
3635                 return false;
3636             }
3637 
3638             return service.isLePeriodicAdvertisingSupported();
3639         }
3640 
3641         @Override
isLeAudioSupported()3642         public int isLeAudioSupported() {
3643             AdapterService service = getService();
3644             if (service == null) {
3645                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3646             }
3647 
3648             Set<Integer> supportedProfileServices =
3649                     Arrays.stream(Config.getSupportedProfiles())
3650                             .boxed()
3651                             .collect(Collectors.toSet());
3652             int[] leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles();
3653 
3654             if (Arrays.stream(leAudioUnicastProfiles)
3655                     .allMatch(supportedProfileServices::contains)) {
3656                 return BluetoothStatusCodes.FEATURE_SUPPORTED;
3657             }
3658 
3659             return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
3660         }
3661 
3662         @Override
isLeAudioBroadcastSourceSupported()3663         public int isLeAudioBroadcastSourceSupported() {
3664             AdapterService service = getService();
3665             if (service == null) {
3666                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3667             }
3668 
3669             long supportBitMask = Config.getSupportedProfilesBitMask();
3670             if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) {
3671                 return BluetoothStatusCodes.FEATURE_SUPPORTED;
3672             }
3673 
3674             return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
3675         }
3676 
3677         @Override
isLeAudioBroadcastAssistantSupported()3678         public int isLeAudioBroadcastAssistantSupported() {
3679             AdapterService service = getService();
3680             if (service == null) {
3681                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3682             }
3683 
3684             int[] supportedProfileServices = Config.getSupportedProfiles();
3685 
3686             if (Arrays.stream(supportedProfileServices)
3687                     .anyMatch(
3688                             profileId ->
3689                                     profileId == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) {
3690                 return BluetoothStatusCodes.FEATURE_SUPPORTED;
3691             }
3692 
3693             return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
3694         }
3695 
3696         @Override
isDistanceMeasurementSupported(AttributionSource source)3697         public int isDistanceMeasurementSupported(AttributionSource source) {
3698             AdapterService service = getService();
3699             if (service == null) {
3700                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3701             } else if (!callerIsSystemOrActiveOrManagedUser(
3702                     service, TAG, "isDistanceMeasurementSupported")) {
3703                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
3704             } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3705                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
3706             }
3707             enforceBluetoothPrivilegedPermission(service);
3708             return BluetoothStatusCodes.FEATURE_SUPPORTED;
3709         }
3710 
3711         @Override
getLeMaximumAdvertisingDataLength()3712         public int getLeMaximumAdvertisingDataLength() {
3713             AdapterService service = getService();
3714             if (service == null) {
3715                 return 0;
3716             }
3717 
3718             return service.getLeMaximumAdvertisingDataLength();
3719         }
3720 
3721         @Override
isActivityAndEnergyReportingSupported()3722         public boolean isActivityAndEnergyReportingSupported() {
3723             AdapterService service = getService();
3724             if (service == null) {
3725                 return false;
3726             }
3727 
3728             return service.mAdapterProperties.isActivityAndEnergyReportingSupported();
3729         }
3730 
3731         @Override
reportActivityInfo(AttributionSource source)3732         public BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) {
3733             AdapterService service = getService();
3734             if (service == null
3735                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3736                 return null;
3737             }
3738 
3739             enforceBluetoothPrivilegedPermission(service);
3740 
3741             return service.reportActivityInfo();
3742         }
3743 
3744         @Override
registerMetadataListener( IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source)3745         public boolean registerMetadataListener(
3746                 IBluetoothMetadataListener listener,
3747                 BluetoothDevice device,
3748                 AttributionSource source) {
3749             AdapterService service = getService();
3750             if (service == null
3751                     || !callerIsSystemOrActiveOrManagedUser(
3752                             service, TAG, "registerMetadataListener")
3753                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3754                 return false;
3755             }
3756 
3757             enforceBluetoothPrivilegedPermission(service);
3758 
3759             List<IBluetoothMetadataListener> list = service.mMetadataListeners.get(device);
3760             if (list == null) {
3761                 list = new ArrayList<>();
3762             } else if (list.contains(listener)) {
3763                 // The device is already registered with this listener
3764                 return true;
3765             }
3766             list.add(listener);
3767             service.mMetadataListeners.put(device, list);
3768             return true;
3769         }
3770 
3771         @Override
unregisterMetadataListener( BluetoothDevice device, AttributionSource source)3772         public boolean unregisterMetadataListener(
3773                 BluetoothDevice device, AttributionSource source) {
3774             AdapterService service = getService();
3775             if (service == null
3776                     || !callerIsSystemOrActiveOrManagedUser(
3777                             service, TAG, "unregisterMetadataListener")
3778                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3779                 return false;
3780             }
3781 
3782             enforceBluetoothPrivilegedPermission(service);
3783 
3784             service.mMetadataListeners.remove(device);
3785             return true;
3786         }
3787 
3788         @Override
setMetadata( BluetoothDevice device, int key, byte[] value, AttributionSource source)3789         public boolean setMetadata(
3790                 BluetoothDevice device, int key, byte[] value, AttributionSource source) {
3791             AdapterService service = getService();
3792             if (service == null
3793                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata")
3794                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3795                 return false;
3796             }
3797 
3798             enforceBluetoothPrivilegedPermission(service);
3799 
3800             if (value.length > BluetoothDevice.METADATA_MAX_LENGTH) {
3801                 return false;
3802             }
3803             return service.mDatabaseManager.setCustomMeta(device, key, value);
3804         }
3805 
3806         @Override
getMetadata(BluetoothDevice device, int key, AttributionSource source)3807         public byte[] getMetadata(BluetoothDevice device, int key, AttributionSource source) {
3808             AdapterService service = getService();
3809             if (service == null
3810                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata")
3811                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3812                 return null;
3813             }
3814 
3815             enforceBluetoothPrivilegedPermission(service);
3816 
3817             return service.mDatabaseManager.getCustomMeta(device, key);
3818         }
3819 
3820         @Override
isRequestAudioPolicyAsSinkSupported( BluetoothDevice device, AttributionSource source)3821         public int isRequestAudioPolicyAsSinkSupported(
3822                 BluetoothDevice device, AttributionSource source) {
3823             AdapterService service = getService();
3824             if (service == null
3825                     || !callerIsSystemOrActiveOrManagedUser(
3826                             service, TAG, "isRequestAudioPolicyAsSinkSupported")
3827                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3828                 return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED;
3829             }
3830             enforceBluetoothPrivilegedPermission(service);
3831             return service.isRequestAudioPolicyAsSinkSupported(device);
3832         }
3833 
3834         @Override
requestAudioPolicyAsSink( BluetoothDevice device, BluetoothSinkAudioPolicy policies, AttributionSource source)3835         public int requestAudioPolicyAsSink(
3836                 BluetoothDevice device,
3837                 BluetoothSinkAudioPolicy policies,
3838                 AttributionSource source) {
3839             AdapterService service = getService();
3840             if (service == null) {
3841                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
3842             } else if (!callerIsSystemOrActiveOrManagedUser(
3843                     service, TAG, "requestAudioPolicyAsSink")) {
3844                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
3845             } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3846                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
3847             }
3848             enforceBluetoothPrivilegedPermission(service);
3849             return service.requestAudioPolicyAsSink(device, policies);
3850         }
3851 
3852         @Override
getRequestedAudioPolicyAsSink( BluetoothDevice device, AttributionSource source)3853         public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(
3854                 BluetoothDevice device, AttributionSource source) {
3855             AdapterService service = getService();
3856             if (service == null
3857                     || !callerIsSystemOrActiveOrManagedUser(
3858                             service, TAG, "getRequestedAudioPolicyAsSink")
3859                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3860                 return null;
3861             }
3862             enforceBluetoothPrivilegedPermission(service);
3863             return service.getRequestedAudioPolicyAsSink(device);
3864         }
3865 
3866         @Override
requestActivityInfo( IBluetoothActivityEnergyInfoListener listener, AttributionSource source)3867         public void requestActivityInfo(
3868                 IBluetoothActivityEnergyInfoListener listener, AttributionSource source) {
3869             BluetoothActivityEnergyInfo info = reportActivityInfo(source);
3870             try {
3871                 listener.onBluetoothActivityEnergyInfoAvailable(info);
3872             } catch (RemoteException e) {
3873                 Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e);
3874             }
3875         }
3876 
3877         @Override
startBrEdr(AttributionSource source)3878         public void startBrEdr(AttributionSource source) {
3879             AdapterService service = getService();
3880             if (service == null
3881                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startBrEdr")
3882                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3883                 return;
3884             }
3885 
3886             enforceBluetoothPrivilegedPermission(service);
3887 
3888             service.startBrEdr();
3889         }
3890 
3891         @Override
stopBle(AttributionSource source)3892         public void stopBle(AttributionSource source) {
3893             AdapterService service = getService();
3894             if (service == null
3895                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopBle")
3896                     || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
3897                 return;
3898             }
3899 
3900             enforceBluetoothPrivilegedPermission(service);
3901 
3902             service.stopBle();
3903         }
3904 
3905         @Override
dump(FileDescriptor fd, String[] args)3906         public void dump(FileDescriptor fd, String[] args) {
3907             PrintWriter writer = new PrintWriter(new FileOutputStream(fd));
3908             AdapterService service = getService();
3909             if (service == null) {
3910                 return;
3911             }
3912 
3913             enforceDumpPermission(service);
3914 
3915             service.dump(fd, writer, args);
3916             writer.close();
3917         }
3918 
3919         @Override
allowLowLatencyAudio(boolean allowed, BluetoothDevice device)3920         public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) {
3921             AdapterService service = getService();
3922             if (service == null
3923                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio")
3924                     || !Utils.checkConnectPermissionForDataDelivery(
3925                             service,
3926                             Utils.getCallingAttributionSource(service),
3927                             "AdapterService allowLowLatencyAudio")) {
3928                 return false;
3929             }
3930             enforceBluetoothPrivilegedPermission(service);
3931             return service.allowLowLatencyAudio(allowed, device);
3932         }
3933 
3934         @Override
startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource attributionSource)3935         public int startRfcommListener(
3936                 String name,
3937                 ParcelUuid uuid,
3938                 PendingIntent pendingIntent,
3939                 AttributionSource attributionSource) {
3940             AdapterService service = getService();
3941             if (service == null
3942                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener")
3943                     || !Utils.checkConnectPermissionForDataDelivery(
3944                             service, attributionSource, "AdapterService startRfcommListener")) {
3945                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
3946             }
3947             enforceBluetoothPrivilegedPermission(service);
3948             return service.startRfcommListener(name, uuid, pendingIntent, attributionSource);
3949         }
3950 
3951         @Override
stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource)3952         public int stopRfcommListener(ParcelUuid uuid, AttributionSource attributionSource) {
3953             AdapterService service = getService();
3954             if (service == null
3955                     || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener")
3956                     || !Utils.checkConnectPermissionForDataDelivery(
3957                             service, attributionSource, "AdapterService stopRfcommListener")) {
3958                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
3959             }
3960             enforceBluetoothPrivilegedPermission(service);
3961             return service.stopRfcommListener(uuid, attributionSource);
3962         }
3963 
3964         @Override
retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource attributionSource)3965         public IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord(
3966                 ParcelUuid uuid, AttributionSource attributionSource) {
3967             AdapterService service = getService();
3968             if (service == null
3969                     || !callerIsSystemOrActiveOrManagedUser(
3970                             service, TAG, "retrievePendingSocketForServiceRecord")
3971                     || !Utils.checkConnectPermissionForDataDelivery(
3972                             service,
3973                             attributionSource,
3974                             "AdapterService retrievePendingSocketForServiceRecord")) {
3975                 return null;
3976             }
3977             enforceBluetoothPrivilegedPermission(service);
3978             return service.retrievePendingSocketForServiceRecord(uuid, attributionSource);
3979         }
3980 
3981         @Override
setForegroundUserId(int userId, AttributionSource attributionSource)3982         public void setForegroundUserId(int userId, AttributionSource attributionSource) {
3983             AdapterService service = getService();
3984             if (service == null
3985                     || !Utils.checkConnectPermissionForDataDelivery(
3986                             service,
3987                             Utils.getCallingAttributionSource(mService),
3988                             "AdapterService setForegroundUserId")) {
3989                 return;
3990             }
3991             enforceBluetoothPrivilegedPermission(service);
3992             Utils.setForegroundUserId(userId);
3993         }
3994 
3995         @Override
setPreferredAudioProfiles( BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source)3996         public int setPreferredAudioProfiles(
3997                 BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source) {
3998             AdapterService service = getService();
3999             if (service == null) {
4000                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4001             }
4002             if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setPreferredAudioProfiles")) {
4003                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4004             }
4005             requireNonNull(device);
4006             requireNonNull(modeToProfileBundle);
4007             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
4008                 throw new IllegalArgumentException("device cannot have an invalid address");
4009             }
4010             if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
4011                 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
4012             }
4013             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4014                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4015             }
4016             enforceBluetoothPrivilegedPermission(service);
4017 
4018             return service.setPreferredAudioProfiles(device, modeToProfileBundle);
4019         }
4020 
4021         @Override
getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source)4022         public Bundle getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source) {
4023             AdapterService service = getService();
4024             if (service == null) {
4025                 return Bundle.EMPTY;
4026             }
4027             if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getPreferredAudioProfiles")) {
4028                 return Bundle.EMPTY;
4029             }
4030             requireNonNull(device);
4031             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
4032                 throw new IllegalArgumentException("device cannot have an invalid address");
4033             }
4034             if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
4035                 return Bundle.EMPTY;
4036             }
4037             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4038                 return Bundle.EMPTY;
4039             }
4040             enforceBluetoothPrivilegedPermission(service);
4041 
4042             return service.getPreferredAudioProfiles(device);
4043         }
4044 
4045         @Override
notifyActiveDeviceChangeApplied( BluetoothDevice device, AttributionSource source)4046         public int notifyActiveDeviceChangeApplied(
4047                 BluetoothDevice device, AttributionSource source) {
4048             AdapterService service = getService();
4049             if (service == null) {
4050                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4051             }
4052             if (!callerIsSystem(TAG, "notifyActiveDeviceChangeApplied")) {
4053                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4054             }
4055             requireNonNull(device);
4056             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
4057                 throw new IllegalArgumentException("device cannot have an invalid address");
4058             }
4059             if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
4060                 return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
4061             }
4062             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4063                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4064             }
4065             enforceBluetoothPrivilegedPermission(service);
4066 
4067             return service.notifyActiveDeviceChangeApplied(device);
4068         }
4069 
4070         @Override
registerPreferredAudioProfilesChangedCallback( IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source)4071         public int registerPreferredAudioProfilesChangedCallback(
4072                 IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
4073             AdapterService service = getService();
4074             if (service == null) {
4075                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4076             }
4077             if (!callerIsSystemOrActiveOrManagedUser(
4078                     service, TAG, "registerPreferredAudioProfilesChangedCallback")) {
4079                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4080             }
4081             requireNonNull(callback);
4082             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4083                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4084             }
4085             enforceBluetoothPrivilegedPermission(service);
4086 
4087             // If LE only mode is enabled, the dual mode audio feature is disabled
4088             if (!isDualModeAudioEnabled()) {
4089                 return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
4090             }
4091 
4092             service.mPreferredAudioProfilesCallbacks.register(callback);
4093             return BluetoothStatusCodes.SUCCESS;
4094         }
4095 
4096         @Override
unregisterPreferredAudioProfilesChangedCallback( IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source)4097         public int unregisterPreferredAudioProfilesChangedCallback(
4098                 IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
4099             AdapterService service = getService();
4100             if (service == null) {
4101                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4102             }
4103             if (!callerIsSystemOrActiveOrManagedUser(
4104                     service, TAG, "unregisterPreferredAudioProfilesChangedCallback")) {
4105                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4106             }
4107             requireNonNull(callback);
4108             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4109                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4110             }
4111             enforceBluetoothPrivilegedPermission(service);
4112 
4113             if (!service.mPreferredAudioProfilesCallbacks.unregister(callback)) {
4114                 Log.e(
4115                         TAG,
4116                         "unregisterPreferredAudioProfilesChangedCallback: callback was never "
4117                                 + "registered");
4118                 return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED;
4119             }
4120             return BluetoothStatusCodes.SUCCESS;
4121         }
4122 
4123         @Override
registerBluetoothQualityReportReadyCallback( IBluetoothQualityReportReadyCallback callback, AttributionSource source)4124         public int registerBluetoothQualityReportReadyCallback(
4125                 IBluetoothQualityReportReadyCallback callback, AttributionSource source) {
4126             AdapterService service = getService();
4127             if (service == null) {
4128                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4129             }
4130             if (!callerIsSystemOrActiveOrManagedUser(
4131                     service, TAG, "registerBluetoothQualityReportReadyCallback")) {
4132                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4133             }
4134             requireNonNull(callback);
4135             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4136                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4137             }
4138             enforceBluetoothPrivilegedPermission(service);
4139 
4140             service.mBluetoothQualityReportReadyCallbacks.register(callback);
4141             return BluetoothStatusCodes.SUCCESS;
4142         }
4143 
4144         @Override
unregisterBluetoothQualityReportReadyCallback( IBluetoothQualityReportReadyCallback callback, AttributionSource source)4145         public int unregisterBluetoothQualityReportReadyCallback(
4146                 IBluetoothQualityReportReadyCallback callback, AttributionSource source) {
4147             AdapterService service = getService();
4148             if (service == null) {
4149                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4150             }
4151             if (!callerIsSystemOrActiveOrManagedUser(
4152                     service, TAG, "unregisterBluetoothQualityReportReadyCallback")) {
4153                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4154             }
4155             requireNonNull(callback);
4156             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4157                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4158             }
4159             enforceBluetoothPrivilegedPermission(service);
4160 
4161             if (!service.mBluetoothQualityReportReadyCallbacks.unregister(callback)) {
4162                 Log.e(
4163                         TAG,
4164                         "unregisterBluetoothQualityReportReadyCallback: callback was never "
4165                                 + "registered");
4166                 return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED;
4167             }
4168             return BluetoothStatusCodes.SUCCESS;
4169         }
4170 
4171         @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
4172         @Override
getOffloadedTransportDiscoveryDataScanSupported( AttributionSource attributionSource)4173         public int getOffloadedTransportDiscoveryDataScanSupported(
4174                 AttributionSource attributionSource) {
4175             AdapterService service = getService();
4176             if (service == null
4177                     || !callerIsSystemOrActiveOrManagedUser(
4178                             service, TAG, "getOffloadedTransportDiscoveryDataScanSupported")
4179                     || !Utils.checkScanPermissionForDataDelivery(
4180                             service,
4181                             attributionSource,
4182                             "getOffloadedTransportDiscoveryDataScanSupported")) {
4183                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
4184             }
4185             enforceBluetoothPrivilegedPermission(service);
4186 
4187             return service.getOffloadedTransportDiscoveryDataScanSupported();
4188         }
4189 
4190         @Override
isMediaProfileConnected(AttributionSource source)4191         public boolean isMediaProfileConnected(AttributionSource source) {
4192             AdapterService service = getService();
4193             if (service == null
4194                     || !Utils.checkConnectPermissionForDataDelivery(
4195                             service, source, "AdapterService.isMediaProfileConnected")) {
4196                 return false;
4197             }
4198             enforceBluetoothPrivilegedPermission(service);
4199 
4200             return service.isMediaProfileConnected();
4201         }
4202 
4203         @Override
getBluetoothGatt()4204         public IBinder getBluetoothGatt() {
4205             AdapterService service = getService();
4206             return service == null ? null : service.getBluetoothGatt();
4207         }
4208 
4209         @Override
getBluetoothScan()4210         public IBinder getBluetoothScan() {
4211             AdapterService service = getService();
4212             return service == null ? null : service.getBluetoothScan();
4213         }
4214 
4215         @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
4216         @Override
unregAllGattClient(AttributionSource source)4217         public void unregAllGattClient(AttributionSource source) {
4218             AdapterService service = getService();
4219             if (service == null) {
4220                 return;
4221             }
4222             enforceBluetoothPrivilegedPermission(service);
4223             service.unregAllGattClient(source);
4224         }
4225 
4226         @Override
getProfile(int profileId)4227         public IBinder getProfile(int profileId) {
4228             AdapterService service = getService();
4229             if (service == null) {
4230                 return null;
4231             }
4232 
4233             return service.getProfile(profileId);
4234         }
4235 
4236         @Override
setActiveAudioDevicePolicy( BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source)4237         public int setActiveAudioDevicePolicy(
4238                 BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) {
4239             AdapterService service = getService();
4240             if (service == null) {
4241                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
4242             }
4243             if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) {
4244                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
4245             }
4246             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
4247                 throw new IllegalArgumentException("device cannot have an invalid address");
4248             }
4249             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4250                 return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4251             }
4252 
4253             enforceBluetoothPrivilegedPermission(service);
4254             return service.mDatabaseManager.setActiveAudioDevicePolicy(
4255                     device, activeAudioDevicePolicy);
4256         }
4257 
4258         @Override
getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source)4259         public int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) {
4260             AdapterService service = getService();
4261             if (service == null) {
4262                 return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
4263             }
4264             if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) {
4265                 throw new IllegalStateException(
4266                         "Caller is not the system or part of the active/managed user");
4267             }
4268             if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
4269                 throw new IllegalArgumentException("device cannot have an invalid address");
4270             }
4271             if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
4272                 return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
4273             }
4274 
4275             enforceBluetoothPrivilegedPermission(service);
4276             return service.mDatabaseManager.getActiveAudioDevicePolicy(device);
4277         }
4278     }
4279 
4280     /**
4281      * Gets the preferred audio profiles for the device. See {@link
4282      * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)} for more details.
4283      *
4284      * @param device is the remote device whose preferences we want to fetch
4285      * @return a Bundle containing the preferred audio profiles for the device
4286      */
getPreferredAudioProfiles(BluetoothDevice device)4287     public Bundle getPreferredAudioProfiles(BluetoothDevice device) {
4288         if (!isDualModeAudioEnabled()
4289                 || mLeAudioService == null
4290                 || !isDualModeAudioSinkDevice(device)) {
4291             return Bundle.EMPTY;
4292         }
4293         // Checks if the device is part of an LE Audio group
4294         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(device);
4295         if (groupDevices.isEmpty()) {
4296             return Bundle.EMPTY;
4297         }
4298 
4299         // If there are no preferences stored, return the defaults
4300         Bundle storedBundle = Bundle.EMPTY;
4301         for (BluetoothDevice groupDevice : groupDevices) {
4302             Bundle groupDevicePreferences = mDatabaseManager.getPreferredAudioProfiles(groupDevice);
4303             if (!groupDevicePreferences.isEmpty()) {
4304                 storedBundle = groupDevicePreferences;
4305                 break;
4306             }
4307         }
4308 
4309         if (storedBundle.isEmpty()) {
4310             Bundle defaultPreferencesBundle = new Bundle();
4311             boolean useDefaultPreferences = false;
4312             if (isOutputOnlyAudioSupported(groupDevices)) {
4313                 // Gets the default output only audio profile or defaults to LE_AUDIO if not present
4314                 int outputOnlyDefault =
4315                         BluetoothProperties.getDefaultOutputOnlyAudioProfile()
4316                                 .orElse(BluetoothProfile.LE_AUDIO);
4317                 if (outputOnlyDefault != BluetoothProfile.A2DP
4318                         && outputOnlyDefault != BluetoothProfile.LE_AUDIO) {
4319                     outputOnlyDefault = BluetoothProfile.LE_AUDIO;
4320                 }
4321                 defaultPreferencesBundle.putInt(
4322                         BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyDefault);
4323                 useDefaultPreferences = true;
4324             }
4325             if (isDuplexAudioSupported(groupDevices)) {
4326                 // Gets the default duplex audio profile or defaults to LE_AUDIO if not present
4327                 int duplexDefault =
4328                         BluetoothProperties.getDefaultDuplexAudioProfile()
4329                                 .orElse(BluetoothProfile.LE_AUDIO);
4330                 if (duplexDefault != BluetoothProfile.HEADSET
4331                         && duplexDefault != BluetoothProfile.LE_AUDIO) {
4332                     duplexDefault = BluetoothProfile.LE_AUDIO;
4333                 }
4334                 defaultPreferencesBundle.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexDefault);
4335                 useDefaultPreferences = true;
4336             }
4337 
4338             if (useDefaultPreferences) {
4339                 return defaultPreferencesBundle;
4340             }
4341         }
4342         return storedBundle;
4343     }
4344 
4345     /**
4346      * Sets the preferred audio profiles for the device. See {@link
4347      * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)} for more details.
4348      *
4349      * @param device is the remote device whose preferences we want to fetch
4350      * @param modeToProfileBundle is the preferences we want to set for the device
4351      * @return whether the preferences were successfully requested
4352      */
setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle)4353     private int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) {
4354         Log.i(TAG, "setPreferredAudioProfiles for device=" + device.getAddressForLogging());
4355         if (!isDualModeAudioEnabled()) {
4356             Log.e(TAG, "setPreferredAudioProfiles called while sysprop is disabled");
4357             return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
4358         }
4359         if (mLeAudioService == null) {
4360             Log.e(TAG, "setPreferredAudioProfiles: LEA service is not up");
4361             return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
4362         }
4363         if (!isDualModeAudioSinkDevice(device)) {
4364             Log.e(TAG, "setPreferredAudioProfiles: Not a dual mode audio device");
4365             return BluetoothStatusCodes.ERROR_NOT_DUAL_MODE_AUDIO_DEVICE;
4366         }
4367         // Checks if the device is part of an LE Audio group
4368         int groupId = mLeAudioService.getGroupId(device);
4369         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId);
4370         if (groupDevices.isEmpty()) {
4371             return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
4372         }
4373 
4374         // Copies relevant keys & values from modeToProfile bundle
4375         Bundle strippedPreferences = new Bundle();
4376         if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)
4377                 && isOutputOnlyAudioSupported(groupDevices)) {
4378             int outputOnlyProfile =
4379                     modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
4380             if (outputOnlyProfile != BluetoothProfile.A2DP
4381                     && outputOnlyProfile != BluetoothProfile.LE_AUDIO) {
4382                 throw new IllegalArgumentException(
4383                         "AUDIO_MODE_OUTPUT_ONLY has invalid value: " + outputOnlyProfile);
4384             }
4385             strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, outputOnlyProfile);
4386         }
4387         if (modeToProfileBundle.containsKey(BluetoothAdapter.AUDIO_MODE_DUPLEX)
4388                 && isDuplexAudioSupported(groupDevices)) {
4389             int duplexProfile = modeToProfileBundle.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
4390             if (duplexProfile != BluetoothProfile.HEADSET
4391                     && duplexProfile != BluetoothProfile.LE_AUDIO) {
4392                 throw new IllegalArgumentException(
4393                         "AUDIO_MODE_DUPLEX has invalid value: " + duplexProfile);
4394             }
4395             strippedPreferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, duplexProfile);
4396         }
4397 
4398         synchronized (mCsipGroupsPendingAudioProfileChanges) {
4399             if (mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) {
4400                 return BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_REQUEST;
4401             }
4402 
4403             Bundle previousPreferences = getPreferredAudioProfiles(device);
4404 
4405             int dbResult =
4406                     mDatabaseManager.setPreferredAudioProfiles(groupDevices, strippedPreferences);
4407             if (dbResult != BluetoothStatusCodes.SUCCESS) {
4408                 return dbResult;
4409             }
4410 
4411             int outputOnlyPreference =
4412                     strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
4413             if (outputOnlyPreference == 0) {
4414                 outputOnlyPreference =
4415                         previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
4416             }
4417             int duplexPreference = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
4418             if (duplexPreference == 0) {
4419                 duplexPreference = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
4420             }
4421 
4422             mLeAudioService.sendAudioProfilePreferencesToNative(
4423                     groupId,
4424                     outputOnlyPreference == BluetoothProfile.LE_AUDIO,
4425                     duplexPreference == BluetoothProfile.LE_AUDIO);
4426 
4427             /* Populates the HashMap to hold requests on the groupId. We will update
4428             numRequestsToAudioFramework after we make requests to the audio framework */
4429             PendingAudioProfilePreferenceRequest holdRequest =
4430                     new PendingAudioProfilePreferenceRequest(strippedPreferences, 0, device);
4431             mCsipGroupsPendingAudioProfileChanges.put(groupId, holdRequest);
4432 
4433             // Notifies audio framework via the handler thread to avoid this blocking calls
4434             mHandler.post(
4435                     () ->
4436                             sendPreferredAudioProfileChangeToAudioFramework(
4437                                     device, strippedPreferences, previousPreferences));
4438             return BluetoothStatusCodes.SUCCESS;
4439         }
4440     }
4441 
4442     /**
4443      * Sends the updated preferred audio profiles to the audio framework.
4444      *
4445      * @param device is the device with updated audio preferences
4446      * @param strippedPreferences is a {@link Bundle} containing the preferences
4447      */
sendPreferredAudioProfileChangeToAudioFramework( BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences)4448     private void sendPreferredAudioProfileChangeToAudioFramework(
4449             BluetoothDevice device, Bundle strippedPreferences, Bundle previousPreferences) {
4450         int newOutput = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
4451         int newDuplex = strippedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
4452         int previousOutput = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
4453         int previousDuplex = previousPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX);
4454 
4455         Log.i(
4456                 TAG,
4457                 "sendPreferredAudioProfileChangeToAudioFramework: changing output from "
4458                         + BluetoothProfile.getProfileName(previousOutput)
4459                         + " to "
4460                         + BluetoothProfile.getProfileName(newOutput)
4461                         + " and duplex from "
4462                         + BluetoothProfile.getProfileName(previousDuplex)
4463                         + " to "
4464                         + BluetoothProfile.getProfileName(newDuplex));
4465 
4466         // If no change from existing preferences, do not inform audio framework
4467         if (previousOutput == newOutput && previousDuplex == newDuplex) {
4468             Log.i(TAG, "No change to preferred audio profiles, no requests to Audio FW");
4469             sendPreferredAudioProfilesCallbackToApps(
4470                     device, strippedPreferences, BluetoothStatusCodes.SUCCESS);
4471             return;
4472         }
4473 
4474         int numRequestsToAudioFw = 0;
4475 
4476         // Checks if the device is part of an LE Audio group
4477         int groupId = mLeAudioService.getGroupId(device);
4478         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(groupId);
4479         if (groupDevices.isEmpty()) {
4480             Log.i(
4481                     TAG,
4482                     "sendPreferredAudioProfileChangeToAudioFramework: Empty LEA group for "
4483                             + "device - "
4484                             + device);
4485             sendPreferredAudioProfilesCallbackToApps(
4486                     device, strippedPreferences, BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED);
4487             return;
4488         }
4489 
4490         synchronized (mCsipGroupsPendingAudioProfileChanges) {
4491             if (previousOutput != newOutput) {
4492                 if (newOutput == BluetoothProfile.A2DP
4493                         && mA2dpService.getActiveDevice() != null
4494                         && groupDevices.contains(mA2dpService.getActiveDevice())) {
4495                     Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to A2DP to Audio FW");
4496                     numRequestsToAudioFw +=
4497                             mA2dpService.sendPreferredAudioProfileChangeToAudioFramework();
4498                 } else if (newOutput == BluetoothProfile.LE_AUDIO
4499                         && mLeAudioService.getActiveGroupId() == groupId) {
4500                     Log.i(TAG, "Sent change for AUDIO_MODE_OUTPUT_ONLY to LE_AUDIO to Audio FW");
4501                     numRequestsToAudioFw +=
4502                             mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework();
4503                 }
4504             }
4505 
4506             if (previousDuplex != newDuplex) {
4507                 if (newDuplex == BluetoothProfile.HEADSET
4508                         && mHeadsetService.getActiveDevice() != null
4509                         && groupDevices.contains(mHeadsetService.getActiveDevice())) {
4510                     Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to HFP to Audio FW");
4511                     // TODO(b/275426145): Add similar HFP method in BluetoothProfileConnectionInfo
4512                     numRequestsToAudioFw +=
4513                             mA2dpService.sendPreferredAudioProfileChangeToAudioFramework();
4514                 } else if (newDuplex == BluetoothProfile.LE_AUDIO
4515                         && mLeAudioService.getActiveGroupId() == groupId) {
4516                     Log.i(TAG, "Sent change for AUDIO_MODE_DUPLEX to LE_AUDIO to Audio FW");
4517                     numRequestsToAudioFw +=
4518                             mLeAudioService.sendPreferredAudioProfileChangeToAudioFramework();
4519                 }
4520             }
4521 
4522             Log.i(
4523                     TAG,
4524                     "sendPreferredAudioProfileChangeToAudioFramework: sent "
4525                             + numRequestsToAudioFw
4526                             + " request(s) to the Audio Framework for device: "
4527                             + device);
4528 
4529             if (numRequestsToAudioFw > 0) {
4530                 mCsipGroupsPendingAudioProfileChanges.put(
4531                         groupId,
4532                         new PendingAudioProfilePreferenceRequest(
4533                                 strippedPreferences, numRequestsToAudioFw, device));
4534 
4535                 Message m =
4536                         mHandler.obtainMessage(
4537                                 MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT);
4538                 m.obj = groupId;
4539                 mHandler.sendMessageDelayed(m, PREFERRED_AUDIO_PROFILE_CHANGE_TIMEOUT.toMillis());
4540                 return;
4541             }
4542         }
4543         sendPreferredAudioProfilesCallbackToApps(
4544                 device, strippedPreferences, BluetoothStatusCodes.SUCCESS);
4545     }
4546 
removeFromPendingAudioProfileChanges(int groupId)4547     private void removeFromPendingAudioProfileChanges(int groupId) {
4548         synchronized (mCsipGroupsPendingAudioProfileChanges) {
4549             Log.i(
4550                     TAG,
4551                     "removeFromPendingAudioProfileChanges: Timeout on change for groupId="
4552                             + groupId);
4553             if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) {
4554                 Log.e(
4555                         TAG,
4556                         "removeFromPendingAudioProfileChanges( "
4557                                 + groupId
4558                                 + ", "
4559                                 + groupId
4560                                 + ") is not pending");
4561                 return;
4562             }
4563         }
4564     }
4565 
4566     /**
4567      * Notification from the audio framework that an active device change has taken effect. See
4568      * {@link BluetoothAdapter#notifyActiveDeviceChangeApplied(BluetoothDevice)} for more details.
4569      *
4570      * @param device the remote device whose preferred audio profiles have been changed
4571      * @return whether the Bluetooth stack acknowledged the change successfully
4572      */
notifyActiveDeviceChangeApplied(BluetoothDevice device)4573     private int notifyActiveDeviceChangeApplied(BluetoothDevice device) {
4574         if (mLeAudioService == null) {
4575             Log.e(TAG, "LE Audio profile not enabled");
4576             return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
4577         }
4578 
4579         int groupId = mLeAudioService.getGroupId(device);
4580         if (groupId == LE_AUDIO_GROUP_ID_INVALID) {
4581             return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
4582         }
4583 
4584         synchronized (mCsipGroupsPendingAudioProfileChanges) {
4585             if (!mCsipGroupsPendingAudioProfileChanges.containsKey(groupId)) {
4586                 Log.e(
4587                         TAG,
4588                         "notifyActiveDeviceChangeApplied, but no pending request for "
4589                                 + "groupId: "
4590                                 + groupId);
4591                 return BluetoothStatusCodes.ERROR_UNKNOWN;
4592             }
4593 
4594             PendingAudioProfilePreferenceRequest pendingRequest =
4595                     mCsipGroupsPendingAudioProfileChanges.get(groupId);
4596 
4597             // If this is the final audio framework request, send callback to apps
4598             if (pendingRequest.mRemainingRequestsToAudioFramework == 1) {
4599                 Log.i(
4600                         TAG,
4601                         "notifyActiveDeviceChangeApplied: Complete for device "
4602                                 + pendingRequest.mDeviceRequested);
4603                 sendPreferredAudioProfilesCallbackToApps(
4604                         pendingRequest.mDeviceRequested,
4605                         pendingRequest.mRequestedPreferences,
4606                         BluetoothStatusCodes.SUCCESS);
4607                 // Removes the timeout from the handler
4608                 mHandler.removeMessages(
4609                         MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT, groupId);
4610             } else if (pendingRequest.mRemainingRequestsToAudioFramework > 1) {
4611                 PendingAudioProfilePreferenceRequest updatedPendingRequest =
4612                         new PendingAudioProfilePreferenceRequest(
4613                                 pendingRequest.mRequestedPreferences,
4614                                 pendingRequest.mRemainingRequestsToAudioFramework - 1,
4615                                 pendingRequest.mDeviceRequested);
4616                 Log.i(
4617                         TAG,
4618                         "notifyActiveDeviceChangeApplied: Updating device "
4619                                 + updatedPendingRequest.mDeviceRequested
4620                                 + " with new remaining requests count="
4621                                 + updatedPendingRequest.mRemainingRequestsToAudioFramework);
4622                 mCsipGroupsPendingAudioProfileChanges.put(groupId, updatedPendingRequest);
4623             } else {
4624                 Log.i(
4625                         TAG,
4626                         "notifyActiveDeviceChangeApplied: "
4627                                 + pendingRequest.mDeviceRequested
4628                                 + " has no remaining requests to audio framework, but is still"
4629                                 + " present in mCsipGroupsPendingAudioProfileChanges");
4630             }
4631         }
4632 
4633         return BluetoothStatusCodes.SUCCESS;
4634     }
4635 
sendPreferredAudioProfilesCallbackToApps( BluetoothDevice device, Bundle preferredAudioProfiles, int status)4636     private void sendPreferredAudioProfilesCallbackToApps(
4637             BluetoothDevice device, Bundle preferredAudioProfiles, int status) {
4638         int n = mPreferredAudioProfilesCallbacks.beginBroadcast();
4639         Log.d(
4640                 TAG,
4641                 "sendPreferredAudioProfilesCallbackToApps() - Broadcasting audio profile "
4642                         + ("change callback to device: " + device)
4643                         + (" and status=" + status)
4644                         + (" to " + n + " receivers."));
4645         for (int i = 0; i < n; i++) {
4646             try {
4647                 mPreferredAudioProfilesCallbacks
4648                         .getBroadcastItem(i)
4649                         .onPreferredAudioProfilesChanged(device, preferredAudioProfiles, status);
4650             } catch (RemoteException e) {
4651                 Log.d(
4652                         TAG,
4653                         "sendPreferredAudioProfilesCallbackToApps() - Callback #"
4654                                 + i
4655                                 + " failed ("
4656                                 + e
4657                                 + ")");
4658             }
4659         }
4660         mPreferredAudioProfilesCallbacks.finishBroadcast();
4661     }
4662 
4663     // ----API Methods--------
4664 
isEnabled()4665     public boolean isEnabled() {
4666         return getState() == BluetoothAdapter.STATE_ON;
4667     }
4668 
getState()4669     public int getState() {
4670         if (mAdapterProperties != null) {
4671             return mAdapterProperties.getState();
4672         }
4673         return BluetoothAdapter.STATE_OFF;
4674     }
4675 
4676     @RequiresPermission(
4677             anyOf = {
4678                 android.Manifest.permission.INTERACT_ACROSS_USERS,
4679                 android.Manifest.permission.MANAGE_USERS,
4680             })
enable(boolean quietMode)4681     public synchronized void enable(boolean quietMode) {
4682         // Enforce the user restriction for disallowing Bluetooth if it was set.
4683         if (mUserManager.hasUserRestrictionForUser(
4684                 UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
4685             Log.d(TAG, "enable() called when Bluetooth was disallowed");
4686             return;
4687         }
4688         if (Flags.fastBindToApp()) {
4689             // The call to init must be done on the main thread
4690             mHandler.post(() -> init());
4691         }
4692 
4693         Log.i(TAG, "enable() - Enable called with quiet mode status =  " + quietMode);
4694         mQuietmode = quietMode;
4695         mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
4696     }
4697 
disable()4698     void disable() {
4699         Log.d(TAG, "disable() called with mRunningProfiles.size() = " + mRunningProfiles.size());
4700         mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_OFF);
4701     }
4702 
getName()4703     public String getName() {
4704         return mAdapterProperties.getName();
4705     }
4706 
getNameLengthForAdvertise()4707     public int getNameLengthForAdvertise() {
4708         return mAdapterProperties.getName().length();
4709     }
4710 
getDiscoveringPackages()4711     List<DiscoveringPackage> getDiscoveringPackages() {
4712         return mDiscoveringPackages;
4713     }
4714 
clearDiscoveringPackages()4715     void clearDiscoveringPackages() {
4716         synchronized (mDiscoveringPackages) {
4717             mDiscoveringPackages.clear();
4718         }
4719     }
4720 
startDiscovery(AttributionSource attributionSource)4721     boolean startDiscovery(AttributionSource attributionSource) {
4722         UserHandle callingUser = Binder.getCallingUserHandle();
4723         Log.d(TAG, "startDiscovery");
4724         String callingPackage = attributionSource.getPackageName();
4725         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4726         boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q);
4727         boolean hasDisavowedLocation =
4728                 Utils.hasDisavowedLocationForScan(this, attributionSource, mTestModeEnabled);
4729         String permission = null;
4730         if (Utils.checkCallerHasNetworkSettingsPermission(this)) {
4731             permission = android.Manifest.permission.NETWORK_SETTINGS;
4732         } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) {
4733             permission = android.Manifest.permission.NETWORK_SETUP_WIZARD;
4734         } else if (!hasDisavowedLocation) {
4735             if (isQApp) {
4736                 if (!Utils.checkCallerHasFineLocation(this, attributionSource, callingUser)) {
4737                     return false;
4738                 }
4739                 permission = android.Manifest.permission.ACCESS_FINE_LOCATION;
4740             } else {
4741                 if (!Utils.checkCallerHasCoarseLocation(this, attributionSource, callingUser)) {
4742                     return false;
4743                 }
4744                 permission = android.Manifest.permission.ACCESS_COARSE_LOCATION;
4745             }
4746         }
4747 
4748         synchronized (mDiscoveringPackages) {
4749             mDiscoveringPackages.add(
4750                     new DiscoveringPackage(callingPackage, permission, hasDisavowedLocation));
4751         }
4752         return mNativeInterface.startDiscovery();
4753     }
4754 
4755     /**
4756      * Same as API method {@link BluetoothAdapter#getBondedDevices()}
4757      *
4758      * @return array of bonded {@link BluetoothDevice} or null on error
4759      */
getBondedDevices()4760     public BluetoothDevice[] getBondedDevices() {
4761         return mAdapterProperties.getBondedDevices();
4762     }
4763 
4764     /**
4765      * Get the database manager to access Bluetooth storage
4766      *
4767      * @return {@link DatabaseManager} or null on error
4768      */
getDatabase()4769     public DatabaseManager getDatabase() {
4770         return mDatabaseManager;
4771     }
4772 
getByteIdentityAddress(BluetoothDevice device)4773     public byte[] getByteIdentityAddress(BluetoothDevice device) {
4774         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4775         if (deviceProp != null && deviceProp.getIdentityAddress() != null) {
4776             return Utils.getBytesFromAddress(deviceProp.getIdentityAddress());
4777         }
4778 
4779         if (Flags.identityAddressNullIfUnknown()) {
4780             // Return null if identity address unknown
4781             return null;
4782         } else {
4783             return Utils.getByteAddress(device);
4784         }
4785     }
4786 
getDeviceFromByte(byte[] address)4787     public BluetoothDevice getDeviceFromByte(byte[] address) {
4788         BluetoothDevice device = mRemoteDevices.getDevice(address);
4789         if (device == null) {
4790             device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
4791         }
4792         return device;
4793     }
4794 
getIdentityAddress(String address)4795     public String getIdentityAddress(String address) {
4796         BluetoothDevice device =
4797                 BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address.toUpperCase());
4798         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4799         if (deviceProp != null && deviceProp.getIdentityAddress() != null) {
4800             return deviceProp.getIdentityAddress();
4801         } else {
4802             if (Flags.identityAddressNullIfUnknown()) {
4803                 // Return null if identity address unknown
4804                 return null;
4805             } else {
4806                 return address;
4807             }
4808         }
4809     }
4810 
4811     private static class CallerInfo {
4812         public String callerPackageName;
4813         public UserHandle user;
4814     }
4815 
createBond( BluetoothDevice device, int transport, OobData remoteP192Data, OobData remoteP256Data, String callingPackage)4816     boolean createBond(
4817             BluetoothDevice device,
4818             int transport,
4819             OobData remoteP192Data,
4820             OobData remoteP256Data,
4821             String callingPackage) {
4822         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4823         if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
4824             // true for BONDING, false for BONDED
4825             return deviceProp.getBondState() == BluetoothDevice.BOND_BONDING;
4826         }
4827 
4828         if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) {
4829             return false;
4830         }
4831 
4832         CallerInfo createBondCaller = new CallerInfo();
4833         createBondCaller.callerPackageName = callingPackage;
4834         createBondCaller.user = Binder.getCallingUserHandle();
4835         mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller);
4836 
4837         mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));
4838 
4839         // Pairing is unreliable while scanning, so cancel discovery
4840         // Note, remove this when native stack improves
4841         mNativeInterface.cancelDiscovery();
4842 
4843         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
4844         msg.obj = device;
4845         msg.arg1 = transport;
4846 
4847         Bundle remoteOobDatasBundle = new Bundle();
4848         boolean setData = false;
4849         if (remoteP192Data != null) {
4850             remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP192, remoteP192Data);
4851             setData = true;
4852         }
4853         if (remoteP256Data != null) {
4854             remoteOobDatasBundle.putParcelable(BondStateMachine.OOBDATAP256, remoteP256Data);
4855             setData = true;
4856         }
4857         if (setData) {
4858             msg.setData(remoteOobDatasBundle);
4859         }
4860         mBondStateMachine.sendMessage(msg);
4861         return true;
4862     }
4863 
4864     /**
4865      * Fetches the local OOB data to give out to remote.
4866      *
4867      * @param transport - specify data transport.
4868      * @param callback - callback used to receive the requested {@link OobData}; null will be
4869      *     ignored silently.
4870      */
generateLocalOobData( int transport, IBluetoothOobDataCallback callback)4871     public synchronized void generateLocalOobData(
4872             int transport, IBluetoothOobDataCallback callback) {
4873         if (callback == null) {
4874             Log.e(TAG, "'callback' argument must not be null!");
4875             return;
4876         }
4877         if (mOobDataCallbackQueue.peek() != null) {
4878             try {
4879                 callback.onError(BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST);
4880             } catch (RemoteException e) {
4881                 Log.e(TAG, "Failed to make callback", e);
4882             }
4883             return;
4884         }
4885         mOobDataCallbackQueue.offer(callback);
4886         mHandler.postDelayed(
4887                 () -> removeFromOobDataCallbackQueue(callback),
4888                 GENERATE_LOCAL_OOB_DATA_TIMEOUT.toMillis());
4889         mNativeInterface.generateLocalOobData(transport);
4890     }
4891 
removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback)4892     private synchronized void removeFromOobDataCallbackQueue(IBluetoothOobDataCallback callback) {
4893         if (callback == null) {
4894             return;
4895         }
4896 
4897         if (mOobDataCallbackQueue.peek() == callback) {
4898             try {
4899                 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN);
4900             } catch (RemoteException e) {
4901                 Log.e(TAG, "Failed to make OobDataCallback to remove callback from queue", e);
4902             }
4903         }
4904     }
4905 
notifyOobDataCallback(int transport, OobData oobData)4906     /* package */ synchronized void notifyOobDataCallback(int transport, OobData oobData) {
4907         if (mOobDataCallbackQueue.peek() == null) {
4908             Log.e(TAG, "Failed to make callback, no callback exists");
4909             return;
4910         }
4911         if (oobData == null) {
4912             try {
4913                 mOobDataCallbackQueue.poll().onError(BluetoothStatusCodes.ERROR_UNKNOWN);
4914             } catch (RemoteException e) {
4915                 Log.e(TAG, "Failed to make callback", e);
4916             }
4917         } else {
4918             try {
4919                 mOobDataCallbackQueue.poll().onOobData(transport, oobData);
4920             } catch (RemoteException e) {
4921                 Log.e(TAG, "Failed to make callback", e);
4922             }
4923         }
4924     }
4925 
isQuietModeEnabled()4926     public boolean isQuietModeEnabled() {
4927         Log.d(TAG, "isQuietModeEnabled() - Enabled = " + mQuietmode);
4928         return mQuietmode;
4929     }
4930 
updateUuids()4931     public void updateUuids() {
4932         Log.d(TAG, "updateUuids() - Updating UUIDs for bonded devices");
4933         BluetoothDevice[] bondedDevices = getBondedDevices();
4934         if (bondedDevices == null) {
4935             return;
4936         }
4937 
4938         for (BluetoothDevice device : bondedDevices) {
4939             mRemoteDevices.updateUuids(device);
4940         }
4941     }
4942 
4943     /**
4944      * Update device UUID changed to {@link BondStateMachine}
4945      *
4946      * @param device remote device of interest
4947      */
deviceUuidUpdated(BluetoothDevice device)4948     public void deviceUuidUpdated(BluetoothDevice device) {
4949         // Notify BondStateMachine for SDP complete / UUID changed.
4950         Message msg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE);
4951         msg.obj = device;
4952         mBondStateMachine.sendMessage(msg);
4953     }
4954 
4955     /**
4956      * Get the bond state of a particular {@link BluetoothDevice}
4957      *
4958      * @param device remote device of interest
4959      * @return bond state
4960      *     <p>Possible values are {@link BluetoothDevice#BOND_NONE}, {@link
4961      *     BluetoothDevice#BOND_BONDING}, {@link BluetoothDevice#BOND_BONDED}.
4962      */
4963     @VisibleForTesting
getBondState(BluetoothDevice device)4964     public int getBondState(BluetoothDevice device) {
4965         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4966         if (deviceProp == null) {
4967             return BluetoothDevice.BOND_NONE;
4968         }
4969         return deviceProp.getBondState();
4970     }
4971 
getConnectionState(BluetoothDevice device)4972     int getConnectionState(BluetoothDevice device) {
4973         final String address = device.getAddress();
4974         if (Flags.apiGetConnectionStateUsingIdentityAddress()) {
4975             int connectionState = mNativeInterface.getConnectionState(getBytesFromAddress(address));
4976             final String identityAddress = getIdentityAddress(address);
4977             if (identityAddress != null) {
4978                 connectionState |=
4979                         mNativeInterface.getConnectionState(getBytesFromAddress(identityAddress));
4980             }
4981             return connectionState;
4982         }
4983         return mNativeInterface.getConnectionState(getBytesFromAddress(address));
4984     }
4985 
getConnectionHandle(BluetoothDevice device, int transport)4986     int getConnectionHandle(BluetoothDevice device, int transport) {
4987         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
4988         if (deviceProp == null) {
4989             return BluetoothDevice.ERROR;
4990         }
4991         return deviceProp.getConnectionHandle(transport);
4992     }
4993 
4994     /**
4995      * Get ASHA Capability
4996      *
4997      * @param device discovered bluetooth device
4998      * @return ASHA capability
4999      */
getAshaCapability(BluetoothDevice device)5000     public int getAshaCapability(BluetoothDevice device) {
5001         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
5002         if (deviceProp == null) {
5003             return BluetoothDevice.ERROR;
5004         }
5005         return deviceProp.getAshaCapability();
5006     }
5007 
5008     /**
5009      * Get ASHA truncated HiSyncId
5010      *
5011      * @param device discovered bluetooth device
5012      * @return ASHA truncated HiSyncId
5013      */
getAshaTruncatedHiSyncId(BluetoothDevice device)5014     public int getAshaTruncatedHiSyncId(BluetoothDevice device) {
5015         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
5016         if (deviceProp == null) {
5017             return BluetoothDevice.ERROR;
5018         }
5019         return deviceProp.getAshaTruncatedHiSyncId();
5020     }
5021 
5022     /**
5023      * Checks whether the device was recently associated with the comapnion app that called {@link
5024      * BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if their
5025      * pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}.
5026      *
5027      * @param device the bluetooth device that is being bonded
5028      * @return true if it was recently associated and we can bypass the dialog, false otherwise
5029      */
canBondWithoutDialog(BluetoothDevice device)5030     public boolean canBondWithoutDialog(BluetoothDevice device) {
5031         if (mBondAttemptCallerInfo.containsKey(device.getAddress())) {
5032             CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress());
5033 
5034             return mCompanionDeviceManager.canPairWithoutPrompt(
5035                     bondCallerInfo.callerPackageName, device.getAddress(), bondCallerInfo.user);
5036         }
5037         return false;
5038     }
5039 
5040     /**
5041      * Returns the package name of the most recent caller that called {@link
5042      * BluetoothDevice#createBond} on the given device.
5043      */
5044     @Nullable
getPackageNameOfBondingApplication(BluetoothDevice device)5045     public String getPackageNameOfBondingApplication(BluetoothDevice device) {
5046         CallerInfo info = mBondAttemptCallerInfo.get(device.getAddress());
5047         if (info == null) {
5048             return null;
5049         }
5050         return info.callerPackageName;
5051     }
5052 
5053     /**
5054      * Sets device as the active devices for the profiles passed into the function.
5055      *
5056      * @param device is the remote bluetooth device
5057      * @param profiles is a constant that references for which profiles we'll be setting the remote
5058      *     device as our active device. One of the following: {@link
5059      *     BluetoothAdapter#ACTIVE_DEVICE_AUDIO}, {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL}
5060      *     {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
5061      * @return false if profiles value is not one of the constants we accept, true otherwise
5062      */
5063     @RequiresPermission(
5064             allOf = {
5065                 android.Manifest.permission.BLUETOOTH_PRIVILEGED,
5066                 android.Manifest.permission.MODIFY_PHONE_STATE,
5067             })
setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles)5068     public boolean setActiveDevice(BluetoothDevice device, @ActiveDeviceUse int profiles) {
5069         boolean setA2dp = false;
5070         boolean setHeadset = false;
5071 
5072         // Determine for which profiles we want to set device as our active device
5073         switch (profiles) {
5074             case BluetoothAdapter.ACTIVE_DEVICE_AUDIO:
5075                 setA2dp = true;
5076                 break;
5077             case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL:
5078                 setHeadset = true;
5079                 break;
5080             case BluetoothAdapter.ACTIVE_DEVICE_ALL:
5081                 setA2dp = true;
5082                 setHeadset = true;
5083                 break;
5084             default:
5085                 return false;
5086         }
5087 
5088         boolean a2dpSupported =
5089                 mA2dpService != null
5090                         && (device == null
5091                                 || mA2dpService.getConnectionPolicy(device)
5092                                         == BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5093         boolean hfpSupported =
5094                 mHeadsetService != null
5095                         && (device == null
5096                                 || mHeadsetService.getConnectionPolicy(device)
5097                                         == BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5098         boolean leAudioSupported =
5099                 mLeAudioService != null
5100                         && (device == null
5101                                 || mLeAudioService.getConnectionPolicy(device)
5102                                         == BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5103 
5104         if (leAudioSupported) {
5105             Log.i(TAG, "setActiveDevice: Setting active Le Audio device " + device);
5106             if (device == null) {
5107                 /* If called by BluetoothAdapter it means Audio should not be stopped.
5108                  * For this reason let's say that fallback device exists
5109                  */
5110                 mLeAudioService.removeActiveDevice(true /* hasFallbackDevice */);
5111             } else {
5112                 mLeAudioService.setActiveDevice(device);
5113             }
5114         }
5115 
5116         if (setA2dp && a2dpSupported) {
5117             Log.i(TAG, "setActiveDevice: Setting active A2dp device " + device);
5118             if (device == null) {
5119                 mA2dpService.removeActiveDevice(false);
5120             } else {
5121                 /* Workaround for the controller issue which is not able to handle correctly
5122                  * A2DP offloader vendor specific command while ISO Data path is set.
5123                  * Proper solutions should be delivered in b/312396770
5124                  */
5125                 if (mLeAudioService != null) {
5126                     List<BluetoothDevice> activeLeAudioDevices = mLeAudioService.getActiveDevices();
5127                     if (activeLeAudioDevices.get(0) != null) {
5128                         mLeAudioService.removeActiveDevice(true);
5129                     }
5130                 }
5131                 mA2dpService.setActiveDevice(device);
5132             }
5133         }
5134 
5135         if (mHearingAidService != null
5136                 && (device == null
5137                         || mHearingAidService.getConnectionPolicy(device)
5138                                 == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) {
5139             Log.i(TAG, "setActiveDevice: Setting active Hearing Aid " + device);
5140             if (device == null) {
5141                 mHearingAidService.removeActiveDevice(false);
5142             } else {
5143                 mHearingAidService.setActiveDevice(device);
5144             }
5145         }
5146 
5147         if (setHeadset && hfpSupported) {
5148             Log.i(TAG, "setActiveDevice: Setting active Headset " + device);
5149             mHeadsetService.setActiveDevice(device);
5150         }
5151 
5152         return true;
5153     }
5154 
5155     /**
5156      * Checks if all supported classic audio profiles are active on this LE Audio device.
5157      *
5158      * @param leAudioDevice the remote device
5159      * @return {@code true} if all supported classic audio profiles are active on this device,
5160      *     {@code false} otherwise
5161      */
isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice)5162     public boolean isAllSupportedClassicAudioProfilesActive(BluetoothDevice leAudioDevice) {
5163         if (mLeAudioService == null) {
5164             return false;
5165         }
5166         boolean a2dpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.A2DP);
5167         boolean hfpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.HEADSET);
5168 
5169         List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(leAudioDevice);
5170         if (hfpSupported && mHeadsetService != null) {
5171             BluetoothDevice activeHfpDevice = mHeadsetService.getActiveDevice();
5172             if (activeHfpDevice == null || !groupDevices.contains(activeHfpDevice)) {
5173                 return false;
5174             }
5175         }
5176         if (a2dpSupported && mA2dpService != null) {
5177             BluetoothDevice activeA2dpDevice = mA2dpService.getActiveDevice();
5178             if (activeA2dpDevice == null || !groupDevices.contains(activeA2dpDevice)) {
5179                 return false;
5180             }
5181         }
5182         return true;
5183     }
5184 
5185     /**
5186      * Get the active devices for the BluetoothProfile specified
5187      *
5188      * @param profile is the profile from which we want the active devices. Possible values are:
5189      *     {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}, {@link
5190      *     BluetoothProfile#HEARING_AID} {@link BluetoothProfile#LE_AUDIO}
5191      * @return A list of active bluetooth devices
5192      */
getActiveDevices(@ctiveDeviceProfile int profile)5193     public List<BluetoothDevice> getActiveDevices(@ActiveDeviceProfile int profile) {
5194         List<BluetoothDevice> activeDevices = new ArrayList<>();
5195 
5196         switch (profile) {
5197             case BluetoothProfile.HEADSET:
5198                 if (mHeadsetService == null) {
5199                     Log.e(TAG, "getActiveDevices: HeadsetService is null");
5200                 } else {
5201                     BluetoothDevice device = mHeadsetService.getActiveDevice();
5202                     if (device != null) {
5203                         activeDevices.add(device);
5204                     }
5205                     Log.i(TAG, "getActiveDevices: Headset device: " + device);
5206                 }
5207                 break;
5208             case BluetoothProfile.A2DP:
5209                 if (mA2dpService == null) {
5210                     Log.e(TAG, "getActiveDevices: A2dpService is null");
5211                 } else {
5212                     BluetoothDevice device = mA2dpService.getActiveDevice();
5213                     if (device != null) {
5214                         activeDevices.add(device);
5215                     }
5216                     Log.i(TAG, "getActiveDevices: A2dp device: " + device);
5217                 }
5218                 break;
5219             case BluetoothProfile.HEARING_AID:
5220                 if (mHearingAidService == null) {
5221                     Log.e(TAG, "getActiveDevices: HearingAidService is null");
5222                 } else {
5223                     activeDevices = mHearingAidService.getActiveDevices();
5224                     Log.i(
5225                             TAG,
5226                             "getActiveDevices: Hearing Aid devices:"
5227                                     + (" Left[" + activeDevices.get(0) + "] -")
5228                                     + (" Right[" + activeDevices.get(1) + "]"));
5229                 }
5230                 break;
5231             case BluetoothProfile.LE_AUDIO:
5232                 if (mLeAudioService == null) {
5233                     Log.e(TAG, "getActiveDevices: LeAudioService is null");
5234                 } else {
5235                     activeDevices = mLeAudioService.getActiveDevices();
5236                     Log.i(
5237                             TAG,
5238                             "getActiveDevices: LeAudio devices:"
5239                                     + (" Lead[" + activeDevices.get(0) + "] -")
5240                                     + (" member_1[" + activeDevices.get(1) + "]"));
5241                 }
5242                 break;
5243             default:
5244                 Log.e(TAG, "getActiveDevices: profile value is not valid");
5245         }
5246         return activeDevices;
5247     }
5248 
5249     /**
5250      * Attempts connection to all enabled and supported bluetooth profiles between the local and
5251      * remote device
5252      *
5253      * @param device is the remote device with which to connect these profiles
5254      * @return {@link BluetoothStatusCodes#SUCCESS} if all profiles connections are attempted, false
5255      *     if an error occurred
5256      */
5257     @RequiresPermission(
5258             allOf = {
5259                 android.Manifest.permission.BLUETOOTH_PRIVILEGED,
5260                 android.Manifest.permission.MODIFY_PHONE_STATE,
5261             })
connectAllEnabledProfiles(BluetoothDevice device)5262     public int connectAllEnabledProfiles(BluetoothDevice device) {
5263         if (!profileServicesRunning()) {
5264             Log.e(TAG, "connectAllEnabledProfiles: Not all profile services running");
5265             return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
5266         }
5267 
5268         // Checks if any profiles are enablde or disabled and if so, only connect enabled profiles
5269         if (!isAllProfilesUnknown(device)) {
5270             return connectEnabledProfiles(device);
5271         }
5272 
5273         connectAllSupportedProfiles(device);
5274 
5275         return BluetoothStatusCodes.SUCCESS;
5276     }
5277 
5278     /**
5279      * Connect all supported bluetooth profiles between the local and remote device
5280      *
5281      * @param device is the remote device with which to connect all supported profiles
5282      */
5283     @RequiresPermission(
5284             allOf = {
5285                 android.Manifest.permission.BLUETOOTH_PRIVILEGED,
5286                 android.Manifest.permission.MODIFY_PHONE_STATE,
5287             })
connectAllSupportedProfiles(BluetoothDevice device)5288     void connectAllSupportedProfiles(BluetoothDevice device) {
5289         int numProfilesConnected = 0;
5290 
5291         // All profile toggles disabled, so connects all supported profiles
5292         if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) {
5293             Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp");
5294             // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED
5295             mA2dpService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5296             numProfilesConnected++;
5297         }
5298         if (mA2dpSinkService != null && isProfileSupported(device, BluetoothProfile.A2DP_SINK)) {
5299             Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink");
5300             mA2dpSinkService.setConnectionPolicy(
5301                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5302             numProfilesConnected++;
5303         }
5304         if (mHeadsetService != null && isProfileSupported(device, BluetoothProfile.HEADSET)) {
5305             Log.i(TAG, "connectAllSupportedProfiles: Connecting Headset Profile");
5306             mHeadsetService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5307             numProfilesConnected++;
5308         }
5309         if (mHeadsetClientService != null
5310                 && isProfileSupported(device, BluetoothProfile.HEADSET_CLIENT)) {
5311             Log.i(TAG, "connectAllSupportedProfiles: Connecting HFP");
5312             mHeadsetClientService.setConnectionPolicy(
5313                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5314             numProfilesConnected++;
5315         }
5316         if (mMapClientService != null && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)) {
5317             Log.i(TAG, "connectAllSupportedProfiles: Connecting MAP");
5318             mMapClientService.setConnectionPolicy(
5319                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5320             numProfilesConnected++;
5321         }
5322         if (mHidHostService != null && isProfileSupported(device, BluetoothProfile.HID_HOST)) {
5323             Log.i(TAG, "connectAllSupportedProfiles: Connecting Hid Host Profile");
5324             mHidHostService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5325             numProfilesConnected++;
5326         }
5327         if (mPanService != null && isProfileSupported(device, BluetoothProfile.PAN)) {
5328             Log.i(TAG, "connectAllSupportedProfiles: Connecting Pan Profile");
5329             mPanService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5330             numProfilesConnected++;
5331         }
5332         if (mPbapClientService != null
5333                 && isProfileSupported(device, BluetoothProfile.PBAP_CLIENT)) {
5334             Log.i(TAG, "connectAllSupportedProfiles: Connecting Pbap");
5335             mPbapClientService.setConnectionPolicy(
5336                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5337             numProfilesConnected++;
5338         }
5339         if (mHearingAidService != null
5340                 && isProfileSupported(device, BluetoothProfile.HEARING_AID)) {
5341             if (mHapClientService != null
5342                     && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) {
5343                 Log.i(
5344                         TAG,
5345                         "connectAllSupportedProfiles: Hearing Access Client Profile is enabled at"
5346                                 + " the same time with Hearing Aid Profile, ignore Hearing Aid"
5347                                 + " Profile");
5348             } else {
5349                 Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Aid Profile");
5350                 mHearingAidService.setConnectionPolicy(
5351                         device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5352                 numProfilesConnected++;
5353             }
5354         }
5355         if (mHapClientService != null && isProfileSupported(device, BluetoothProfile.HAP_CLIENT)) {
5356             Log.i(TAG, "connectAllSupportedProfiles: Connecting Hearing Access Client Profile");
5357             mHapClientService.setConnectionPolicy(
5358                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5359             numProfilesConnected++;
5360         }
5361         if (mVolumeControlService != null
5362                 && isProfileSupported(device, BluetoothProfile.VOLUME_CONTROL)) {
5363             Log.i(TAG, "connectAllSupportedProfiles: Connecting Volume Control Profile");
5364             mVolumeControlService.setConnectionPolicy(
5365                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5366             numProfilesConnected++;
5367         }
5368         if (mCsipSetCoordinatorService != null
5369                 && isProfileSupported(device, BluetoothProfile.CSIP_SET_COORDINATOR)) {
5370             Log.i(TAG, "connectAllSupportedProfiles: Connecting Coordinated Set Profile");
5371             mCsipSetCoordinatorService.setConnectionPolicy(
5372                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5373             numProfilesConnected++;
5374         }
5375         if (mLeAudioService != null && isProfileSupported(device, BluetoothProfile.LE_AUDIO)) {
5376             Log.i(TAG, "connectAllSupportedProfiles: Connecting LeAudio profile (BAP)");
5377             mLeAudioService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5378             numProfilesConnected++;
5379         }
5380         if (mBassClientService != null
5381                 && isProfileSupported(device, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) {
5382             Log.i(TAG, "connectAllSupportedProfiles: Connecting LE Broadcast Assistant Profile");
5383             mBassClientService.setConnectionPolicy(
5384                     device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5385             numProfilesConnected++;
5386         }
5387         if (mBatteryService != null && isProfileSupported(device, BluetoothProfile.BATTERY)) {
5388             Log.i(TAG, "connectAllSupportedProfiles: Connecting Battery Service");
5389             mBatteryService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
5390             numProfilesConnected++;
5391         }
5392 
5393         Log.i(
5394                 TAG,
5395                 "connectAllSupportedProfiles: Number of Profiles Connected: "
5396                         + numProfilesConnected);
5397     }
5398 
5399     /**
5400      * Disconnects all enabled and supported bluetooth profiles between the local and remote device
5401      *
5402      * @param device is the remote device with which to disconnect these profiles
5403      * @return true if all profiles successfully disconnected, false if an error occurred
5404      */
5405     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
disconnectAllEnabledProfiles(BluetoothDevice device)5406     public int disconnectAllEnabledProfiles(BluetoothDevice device) {
5407         if (!profileServicesRunning()) {
5408             Log.e(TAG, "disconnectAllEnabledProfiles: Not all profile services bound");
5409             return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
5410         }
5411 
5412         if (mA2dpService != null
5413                 && (mA2dpService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5414                         || mA2dpService.getConnectionState(device)
5415                                 == BluetoothProfile.STATE_CONNECTING)) {
5416             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp");
5417             mA2dpService.disconnect(device);
5418         }
5419         if (mA2dpSinkService != null
5420                 && (mA2dpSinkService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5421                         || mA2dpSinkService.getConnectionState(device)
5422                                 == BluetoothProfile.STATE_CONNECTING)) {
5423             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink");
5424             mA2dpSinkService.disconnect(device);
5425         }
5426         if (mHeadsetService != null
5427                 && (mHeadsetService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5428                         || mHeadsetService.getConnectionState(device)
5429                                 == BluetoothProfile.STATE_CONNECTING)) {
5430             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Headset Profile");
5431             mHeadsetService.disconnect(device);
5432         }
5433         if (mHeadsetClientService != null
5434                 && (mHeadsetClientService.getConnectionState(device)
5435                                 == BluetoothProfile.STATE_CONNECTED
5436                         || mHeadsetClientService.getConnectionState(device)
5437                                 == BluetoothProfile.STATE_CONNECTING)) {
5438             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP");
5439             mHeadsetClientService.disconnect(device);
5440         }
5441         if (mMapClientService != null
5442                 && (mMapClientService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5443                         || mMapClientService.getConnectionState(device)
5444                                 == BluetoothProfile.STATE_CONNECTING)) {
5445             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP Client");
5446             mMapClientService.disconnect(device);
5447         }
5448         if (mMapService != null
5449                 && (mMapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5450                         || mMapService.getConnectionState(device)
5451                                 == BluetoothProfile.STATE_CONNECTING)) {
5452             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting MAP");
5453             mMapService.disconnect(device);
5454         }
5455         if (mHidDeviceService != null
5456                 && (mHidDeviceService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5457                         || mHidDeviceService.getConnectionState(device)
5458                                 == BluetoothProfile.STATE_CONNECTING)) {
5459             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Device Profile");
5460             mHidDeviceService.disconnect(device);
5461         }
5462         if (mHidHostService != null
5463                 && (mHidHostService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5464                         || mHidHostService.getConnectionState(device)
5465                                 == BluetoothProfile.STATE_CONNECTING)) {
5466             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hid Host Profile");
5467             mHidHostService.disconnect(device);
5468         }
5469         if (mPanService != null
5470                 && (mPanService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5471                         || mPanService.getConnectionState(device)
5472                                 == BluetoothProfile.STATE_CONNECTING)) {
5473             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pan Profile");
5474             mPanService.disconnect(device);
5475         }
5476         if (mPbapClientService != null
5477                 && (mPbapClientService.getConnectionState(device)
5478                                 == BluetoothProfile.STATE_CONNECTED
5479                         || mPbapClientService.getConnectionState(device)
5480                                 == BluetoothProfile.STATE_CONNECTING)) {
5481             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Client");
5482             mPbapClientService.disconnect(device);
5483         }
5484         if (mPbapService != null
5485                 && (mPbapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5486                         || mPbapService.getConnectionState(device)
5487                                 == BluetoothProfile.STATE_CONNECTING)) {
5488             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Pbap Server");
5489             mPbapService.disconnect(device);
5490         }
5491         if (mHearingAidService != null
5492                 && (mHearingAidService.getConnectionState(device)
5493                                 == BluetoothProfile.STATE_CONNECTED
5494                         || mHearingAidService.getConnectionState(device)
5495                                 == BluetoothProfile.STATE_CONNECTING)) {
5496             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Aid Profile");
5497             mHearingAidService.disconnect(device);
5498         }
5499         if (mHapClientService != null
5500                 && (mHapClientService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5501                         || mHapClientService.getConnectionState(device)
5502                                 == BluetoothProfile.STATE_CONNECTING)) {
5503             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Hearing Access Profile Client");
5504             mHapClientService.disconnect(device);
5505         }
5506         if (mVolumeControlService != null
5507                 && (mVolumeControlService.getConnectionState(device)
5508                                 == BluetoothProfile.STATE_CONNECTED
5509                         || mVolumeControlService.getConnectionState(device)
5510                                 == BluetoothProfile.STATE_CONNECTING)) {
5511             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Volume Control Profile");
5512             mVolumeControlService.disconnect(device);
5513         }
5514         if (mSapService != null
5515                 && (mSapService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5516                         || mSapService.getConnectionState(device)
5517                                 == BluetoothProfile.STATE_CONNECTING)) {
5518             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Sap Profile");
5519             mSapService.disconnect(device);
5520         }
5521         if (mCsipSetCoordinatorService != null
5522                 && (mCsipSetCoordinatorService.getConnectionState(device)
5523                                 == BluetoothProfile.STATE_CONNECTED
5524                         || mCsipSetCoordinatorService.getConnectionState(device)
5525                                 == BluetoothProfile.STATE_CONNECTING)) {
5526             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting Coordinater Set Profile");
5527             mCsipSetCoordinatorService.disconnect(device);
5528         }
5529         if (mLeAudioService != null
5530                 && (mLeAudioService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5531                         || mLeAudioService.getConnectionState(device)
5532                                 == BluetoothProfile.STATE_CONNECTING)) {
5533             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting LeAudio profile (BAP)");
5534             mLeAudioService.disconnect(device);
5535         }
5536         if (mBassClientService != null
5537                 && (mBassClientService.getConnectionState(device)
5538                                 == BluetoothProfile.STATE_CONNECTED
5539                         || mBassClientService.getConnectionState(device)
5540                                 == BluetoothProfile.STATE_CONNECTING)) {
5541             Log.i(
5542                     TAG,
5543                     "disconnectAllEnabledProfiles: Disconnecting "
5544                             + "LE Broadcast Assistant Profile");
5545             mBassClientService.disconnect(device);
5546         }
5547         if (mBatteryService != null
5548                 && (mBatteryService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
5549                         || mBatteryService.getConnectionState(device)
5550                                 == BluetoothProfile.STATE_CONNECTING)) {
5551             Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting " + "Battery Service");
5552             mBatteryService.disconnect(device);
5553         }
5554 
5555         return BluetoothStatusCodes.SUCCESS;
5556     }
5557 
5558     /**
5559      * Same as API method {@link BluetoothDevice#getName()}
5560      *
5561      * @param device remote device of interest
5562      * @return remote device name
5563      */
getRemoteName(BluetoothDevice device)5564     public String getRemoteName(BluetoothDevice device) {
5565         if (mRemoteDevices == null) {
5566             return null;
5567         }
5568         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
5569         if (deviceProp == null) {
5570             return null;
5571         }
5572         return deviceProp.getName();
5573     }
5574 
5575     /**
5576      * Get UUIDs for service supported by a remote device
5577      *
5578      * @param device the remote device that we want to get UUIDs from
5579      * @return the uuids of the remote device
5580      */
getRemoteUuids(BluetoothDevice device)5581     public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
5582         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
5583         if (deviceProp == null) {
5584             return null;
5585         }
5586         return deviceProp.getUuids();
5587     }
5588 
getBluetoothConnectionCallbacks()5589     public Set<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() {
5590         return mBluetoothConnectionCallbacks;
5591     }
5592 
5593     /**
5594      * Converts HCI disconnect reasons to Android disconnect reasons.
5595      *
5596      * <p>The HCI Error Codes used for ACL disconnect reasons propagated up from native code were
5597      * copied from: packages/modules/Bluetooth/system/stack/include/hci_error_code.h
5598      *
5599      * <p>These error codes are specified and described in Bluetooth Core Spec v5.1, Vol 2, Part D.
5600      *
5601      * @param hciReason is the raw HCI disconnect reason from native.
5602      * @return the Android disconnect reason for apps.
5603      */
5604     static @BluetoothAdapter.BluetoothConnectionCallback.DisconnectReason int
hciToAndroidDisconnectReason(int hciReason)5605             hciToAndroidDisconnectReason(int hciReason) {
5606         switch (hciReason) {
5607             case /*HCI_SUCCESS*/ 0x00:
5608             case /*HCI_ERR_UNSPECIFIED*/ 0x1F:
5609             case /*HCI_ERR_UNDEFINED*/ 0xff:
5610                 return BluetoothStatusCodes.ERROR_UNKNOWN;
5611             case /*HCI_ERR_ILLEGAL_COMMAND*/ 0x01:
5612             case /*HCI_ERR_NO_CONNECTION*/ 0x02:
5613             case /*HCI_ERR_HW_FAILURE*/ 0x03:
5614             case /*HCI_ERR_DIFF_TRANSACTION_COLLISION*/ 0x2A:
5615             case /*HCI_ERR_ROLE_SWITCH_PENDING*/ 0x32:
5616             case /*HCI_ERR_ROLE_SWITCH_FAILED*/ 0x35:
5617                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL;
5618             case /*HCI_ERR_PAGE_TIMEOUT*/ 0x04:
5619             case /*HCI_ERR_CONNECTION_TOUT*/ 0x08:
5620             case /*HCI_ERR_HOST_TIMEOUT*/ 0x10:
5621             case /*HCI_ERR_LMP_RESPONSE_TIMEOUT*/ 0x22:
5622             case /*HCI_ERR_ADVERTISING_TIMEOUT*/ 0x3C:
5623             case /*HCI_ERR_CONN_FAILED_ESTABLISHMENT*/ 0x3E:
5624                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT;
5625             case /*HCI_ERR_AUTH_FAILURE*/ 0x05:
5626             case /*HCI_ERR_KEY_MISSING*/ 0x06:
5627             case /*HCI_ERR_HOST_REJECT_SECURITY*/ 0x0E:
5628             case /*HCI_ERR_REPEATED_ATTEMPTS*/ 0x17:
5629             case /*HCI_ERR_PAIRING_NOT_ALLOWED*/ 0x18:
5630             case /*HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE*/ 0x25:
5631             case /*HCI_ERR_UNIT_KEY_USED*/ 0x26:
5632             case /*HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED*/ 0x29:
5633             case /*HCI_ERR_INSUFFCIENT_SECURITY*/ 0x2F:
5634             case /*HCI_ERR_HOST_BUSY_PAIRING*/ 0x38:
5635                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY;
5636             case /*HCI_ERR_MEMORY_FULL*/ 0x07:
5637             case /*HCI_ERR_MAX_NUM_OF_CONNECTIONS*/ 0x09:
5638             case /*HCI_ERR_MAX_NUM_OF_SCOS*/ 0x0A:
5639             case /*HCI_ERR_COMMAND_DISALLOWED*/ 0x0C:
5640             case /*HCI_ERR_HOST_REJECT_RESOURCES*/ 0x0D:
5641             case /*HCI_ERR_LIMIT_REACHED*/ 0x43:
5642                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED;
5643             case /*HCI_ERR_CONNECTION_EXISTS*/ 0x0B:
5644                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS;
5645             case /*HCI_ERR_HOST_REJECT_DEVICE*/ 0x0F:
5646                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY;
5647             case /*HCI_ERR_ILLEGAL_PARAMETER_FMT*/ 0x12:
5648                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS;
5649             case /*HCI_ERR_PEER_USER*/ 0x13:
5650                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST;
5651             case /*HCI_ERR_REMOTE_POWER_OFF*/ 0x15:
5652                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST;
5653             case /*HCI_ERR_CONN_CAUSE_LOCAL_HOST*/ 0x16:
5654                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST;
5655             case /*HCI_ERR_UNSUPPORTED_REM_FEATURE*/ 0x1A:
5656                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE;
5657             case /*HCI_ERR_UNACCEPT_CONN_INTERVAL*/ 0x3B:
5658                 return BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS;
5659             default:
5660                 Log.e(TAG, "Invalid HCI disconnect reason: " + hciReason);
5661                 return BluetoothStatusCodes.ERROR_UNKNOWN;
5662         }
5663     }
5664 
logUserBondResponse(BluetoothDevice device, boolean accepted, int event)5665     void logUserBondResponse(BluetoothDevice device, boolean accepted, int event) {
5666         final long token = Binder.clearCallingIdentity();
5667         try {
5668             BluetoothStatsLog.write(
5669                     BluetoothStatsLog.BLUETOOTH_BOND_STATE_CHANGED,
5670                     obfuscateAddress(device),
5671                     0,
5672                     device.getType(),
5673                     BluetoothDevice.BOND_BONDING,
5674                     event,
5675                     accepted ? 0 : BluetoothDevice.UNBOND_REASON_AUTH_REJECTED);
5676         } finally {
5677             Binder.restoreCallingIdentity(token);
5678         }
5679     }
5680 
getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile)5681     int getDeviceAccessFromPrefs(BluetoothDevice device, String prefFile) {
5682         SharedPreferences prefs = getSharedPreferences(prefFile, Context.MODE_PRIVATE);
5683         if (!prefs.contains(device.getAddress())) {
5684             return BluetoothDevice.ACCESS_UNKNOWN;
5685         }
5686         return prefs.getBoolean(device.getAddress(), false)
5687                 ? BluetoothDevice.ACCESS_ALLOWED
5688                 : BluetoothDevice.ACCESS_REJECTED;
5689     }
5690 
setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile)5691     void setDeviceAccessFromPrefs(BluetoothDevice device, int value, String prefFile) {
5692         SharedPreferences pref = getSharedPreferences(prefFile, Context.MODE_PRIVATE);
5693         SharedPreferences.Editor editor = pref.edit();
5694         if (value == BluetoothDevice.ACCESS_UNKNOWN) {
5695             editor.remove(device.getAddress());
5696         } else {
5697             editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED);
5698         }
5699         editor.apply();
5700     }
5701 
setPhonebookAccessPermission(BluetoothDevice device, int value)5702     public void setPhonebookAccessPermission(BluetoothDevice device, int value) {
5703         setDeviceAccessFromPrefs(device, value, PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE);
5704     }
5705 
setMessageAccessPermission(BluetoothDevice device, int value)5706     public void setMessageAccessPermission(BluetoothDevice device, int value) {
5707         setDeviceAccessFromPrefs(device, value, MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE);
5708     }
5709 
setSimAccessPermission(BluetoothDevice device, int value)5710     public void setSimAccessPermission(BluetoothDevice device, int value) {
5711         setDeviceAccessFromPrefs(device, value, SIM_ACCESS_PERMISSION_PREFERENCE_FILE);
5712     }
5713 
isRpaOffloadSupported()5714     public boolean isRpaOffloadSupported() {
5715         return mAdapterProperties.isRpaOffloadSupported();
5716     }
5717 
getNumOfOffloadedIrkSupported()5718     public int getNumOfOffloadedIrkSupported() {
5719         return mAdapterProperties.getNumOfOffloadedIrkSupported();
5720     }
5721 
getNumOfOffloadedScanFilterSupported()5722     public int getNumOfOffloadedScanFilterSupported() {
5723         return mAdapterProperties.getNumOfOffloadedScanFilterSupported();
5724     }
5725 
getOffloadedScanResultStorage()5726     public int getOffloadedScanResultStorage() {
5727         return mAdapterProperties.getOffloadedScanResultStorage();
5728     }
5729 
isLe2MPhySupported()5730     public boolean isLe2MPhySupported() {
5731         return mAdapterProperties.isLe2MPhySupported();
5732     }
5733 
isLeCodedPhySupported()5734     public boolean isLeCodedPhySupported() {
5735         return mAdapterProperties.isLeCodedPhySupported();
5736     }
5737 
isLeExtendedAdvertisingSupported()5738     public boolean isLeExtendedAdvertisingSupported() {
5739         return mAdapterProperties.isLeExtendedAdvertisingSupported();
5740     }
5741 
isLePeriodicAdvertisingSupported()5742     public boolean isLePeriodicAdvertisingSupported() {
5743         return mAdapterProperties.isLePeriodicAdvertisingSupported();
5744     }
5745 
5746     /**
5747      * Check if the LE audio broadcast source feature is supported.
5748      *
5749      * @return true, if the LE audio broadcast source is supported
5750      */
isLeAudioBroadcastSourceSupported()5751     public boolean isLeAudioBroadcastSourceSupported() {
5752         return mAdapterProperties.isLePeriodicAdvertisingSupported()
5753                 && mAdapterProperties.isLeExtendedAdvertisingSupported()
5754                 && mAdapterProperties.isLeIsochronousBroadcasterSupported();
5755     }
5756 
5757     /**
5758      * Check if the LE audio broadcast assistant feature is supported.
5759      *
5760      * @return true, if the LE audio broadcast assistant is supported
5761      */
isLeAudioBroadcastAssistantSupported()5762     public boolean isLeAudioBroadcastAssistantSupported() {
5763         return mAdapterProperties.isLePeriodicAdvertisingSupported()
5764                 && mAdapterProperties.isLeExtendedAdvertisingSupported()
5765                 && (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported()
5766                         || mAdapterProperties
5767                                 .isLePeriodicAdvertisingSyncTransferRecipientSupported());
5768     }
5769 
5770     /**
5771      * Check if the LE channel sounding feature is supported.
5772      *
5773      * @return true, if the LE channel sounding is supported
5774      */
isLeChannelSoundingSupported()5775     public boolean isLeChannelSoundingSupported() {
5776         return mAdapterProperties.isLeChannelSoundingSupported();
5777     }
5778 
getSupportedProfilesBitMask()5779     public long getSupportedProfilesBitMask() {
5780         return Config.getSupportedProfilesBitMask();
5781     }
5782 
5783     /**
5784      * Check if the LE audio CIS central feature is supported.
5785      *
5786      * @return true, if the LE audio CIS central is supported
5787      */
isLeConnectedIsochronousStreamCentralSupported()5788     public boolean isLeConnectedIsochronousStreamCentralSupported() {
5789         return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported();
5790     }
5791 
getLeMaximumAdvertisingDataLength()5792     public int getLeMaximumAdvertisingDataLength() {
5793         return mAdapterProperties.getLeMaximumAdvertisingDataLength();
5794     }
5795 
5796     /**
5797      * Get the maximum number of connected audio devices.
5798      *
5799      * @return the maximum number of connected audio devices
5800      */
getMaxConnectedAudioDevices()5801     public int getMaxConnectedAudioDevices() {
5802         return mAdapterProperties.getMaxConnectedAudioDevices();
5803     }
5804 
5805     /**
5806      * Check whether A2DP offload is enabled.
5807      *
5808      * @return true if A2DP offload is enabled
5809      */
isA2dpOffloadEnabled()5810     public boolean isA2dpOffloadEnabled() {
5811         return mAdapterProperties.isA2dpOffloadEnabled();
5812     }
5813 
5814     /** Register a bluetooth state callback */
registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback)5815     public void registerBluetoothStateCallback(Executor executor, BluetoothStateCallback callback) {
5816         mLocalCallbacks.put(callback, executor);
5817     }
5818 
5819     /** Unregister a bluetooth state callback */
unregisterBluetoothStateCallback(BluetoothStateCallback callback)5820     public void unregisterBluetoothStateCallback(BluetoothStateCallback callback) {
5821         mLocalCallbacks.remove(callback);
5822     }
5823 
5824     @VisibleForTesting
registerRemoteCallback(IBluetoothCallback callback)5825     void registerRemoteCallback(IBluetoothCallback callback) {
5826         mRemoteCallbacks.register(callback);
5827     }
5828 
5829     @VisibleForTesting
unregisterRemoteCallback(IBluetoothCallback callback)5830     void unregisterRemoteCallback(IBluetoothCallback callback) {
5831         mRemoteCallbacks.unregister(callback);
5832     }
5833 
5834     @VisibleForTesting
startBrEdr()5835     void startBrEdr() {
5836         mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);
5837     }
5838 
5839     @VisibleForTesting
stopBle()5840     void stopBle() {
5841         mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
5842     }
5843 
5844     @VisibleForTesting
factoryReset()5845     boolean factoryReset() {
5846         mDatabaseManager.factoryReset();
5847 
5848         if (mBluetoothKeystoreService != null) {
5849             mBluetoothKeystoreService.factoryReset();
5850         }
5851 
5852         if (mBtCompanionManager != null) {
5853             mBtCompanionManager.factoryReset();
5854         }
5855 
5856         return mNativeInterface.factoryReset();
5857     }
5858 
5859     @VisibleForTesting
getScanMode()5860     int getScanMode() {
5861         return mAdapterProperties.getScanMode();
5862     }
5863 
5864     @VisibleForTesting
reportActivityInfo()5865     BluetoothActivityEnergyInfo reportActivityInfo() {
5866         if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON
5867                 || !mAdapterProperties.isActivityAndEnergyReportingSupported()) {
5868             return null;
5869         }
5870 
5871         // Pull the data. The callback will notify mEnergyInfoLock.
5872         mNativeInterface.readEnergyInfo();
5873 
5874         synchronized (mEnergyInfoLock) {
5875             long now = System.currentTimeMillis();
5876             final long deadline = now + CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS;
5877             while (now < deadline) {
5878                 try {
5879                     mEnergyInfoLock.wait(deadline - now);
5880                     break;
5881                 } catch (InterruptedException e) {
5882                     now = System.currentTimeMillis();
5883                 }
5884             }
5885 
5886             final BluetoothActivityEnergyInfo info =
5887                     new BluetoothActivityEnergyInfo(
5888                             SystemClock.elapsedRealtime(),
5889                             mStackReportedState,
5890                             mTxTimeTotalMs,
5891                             mRxTimeTotalMs,
5892                             mIdleTimeTotalMs,
5893                             mEnergyUsedTotalVoltAmpSecMicro);
5894 
5895             // Copy the traffic objects whose byte counts are > 0
5896             final List<UidTraffic> result = new ArrayList<>();
5897             for (int i = 0; i < mUidTraffic.size(); i++) {
5898                 final UidTraffic traffic = mUidTraffic.valueAt(i);
5899                 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) {
5900                     result.add(traffic.clone());
5901                 }
5902             }
5903 
5904             info.setUidTraffic(result);
5905 
5906             return info;
5907         }
5908     }
5909 
getTotalNumOfTrackableAdvertisements()5910     public int getTotalNumOfTrackableAdvertisements() {
5911         return mAdapterProperties.getTotalNumOfTrackableAdvertisements();
5912     }
5913 
5914     /**
5915      * Return if offloaded TDS filter is supported.
5916      *
5917      * @return {@code BluetoothStatusCodes.FEATURE_SUPPORTED} if supported
5918      */
getOffloadedTransportDiscoveryDataScanSupported()5919     public int getOffloadedTransportDiscoveryDataScanSupported() {
5920         if (mAdapterProperties.isOffloadedTransportDiscoveryDataScanSupported()) {
5921             return BluetoothStatusCodes.FEATURE_SUPPORTED;
5922         }
5923         return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
5924     }
5925 
getBluetoothGatt()5926     IBinder getBluetoothGatt() {
5927         return mGattService == null ? null : mGattService.getBinder();
5928     }
5929 
getBluetoothScan()5930     IBinder getBluetoothScan() {
5931         return mScanController == null ? null : mScanController.getBinder();
5932     }
5933 
unregAllGattClient(AttributionSource source)5934     void unregAllGattClient(AttributionSource source) {
5935         if (mGattService != null) {
5936             mGattService.unregAll(source);
5937         }
5938     }
5939 
getProfile(int profileId)5940     IBinder getProfile(int profileId) {
5941         if (getState() == BluetoothAdapter.STATE_TURNING_ON) {
5942             return null;
5943         }
5944 
5945         // LE_AUDIO_BROADCAST is not associated with a service and use LE_AUDIO's Binder
5946         if (profileId == BluetoothProfile.LE_AUDIO_BROADCAST) {
5947             profileId = BluetoothProfile.LE_AUDIO;
5948         }
5949 
5950         ProfileService profile = mStartedProfiles.get(profileId);
5951         if (profile != null) {
5952             return profile.getBinder();
5953         } else {
5954             return null;
5955         }
5956     }
5957 
isMediaProfileConnected()5958     boolean isMediaProfileConnected() {
5959         if (mA2dpService != null && mA2dpService.getConnectedDevices().size() > 0) {
5960             Log.d(TAG, "isMediaProfileConnected. A2dp is connected");
5961             return true;
5962         } else if (mHearingAidService != null
5963                 && mHearingAidService.getConnectedDevices().size() > 0) {
5964             Log.d(TAG, "isMediaProfileConnected. HearingAid is connected");
5965             return true;
5966         } else if (mLeAudioService != null && mLeAudioService.getConnectedDevices().size() > 0) {
5967             Log.d(TAG, "isMediaProfileConnected. LeAudio is connected");
5968             return true;
5969         } else {
5970             Log.d(
5971                     TAG,
5972                     "isMediaProfileConnected: no Media connected."
5973                             + (" A2dp=" + mA2dpService)
5974                             + (" HearingAid=" + mHearingAidService)
5975                             + (" LeAudio=" + mLeAudioService));
5976             return false;
5977         }
5978     }
5979 
5980     /** Update PhonePolicy when new {@link BluetoothDevice} creates an ACL connection. */
updatePhonePolicyOnAclConnect(BluetoothDevice device)5981     public void updatePhonePolicyOnAclConnect(BluetoothDevice device) {
5982         if (mPhonePolicy != null) {
5983             mPhonePolicy.handleAclConnected(device);
5984         }
5985     }
5986 
5987     /**
5988      * Notify {@link BluetoothProfile} when ACL connection disconnects from {@link BluetoothDevice}
5989      * for a given {@code transport}.
5990      */
notifyAclDisconnected(BluetoothDevice device, int transport)5991     public void notifyAclDisconnected(BluetoothDevice device, int transport) {
5992         if (mMapService != null && mMapService.isAvailable()) {
5993             mMapService.aclDisconnected(device);
5994         }
5995         if (mMapClientService != null && mMapClientService.isAvailable()) {
5996             mMapClientService.aclDisconnected(device, transport);
5997         }
5998         if (mSapService != null && mSapService.isAvailable()) {
5999             mSapService.aclDisconnected(device);
6000         }
6001         if (mPbapClientService != null && mPbapClientService.isAvailable()) {
6002             mPbapClientService.aclDisconnected(device, transport);
6003         }
6004     }
6005 
6006     /**
6007      * Notify GATT of a Bluetooth profile's connection state change for a given {@link
6008      * BluetoothProfile}.
6009      */
notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState)6010     public void notifyProfileConnectionStateChangeToGatt(int profile, int fromState, int toState) {
6011         if (mGattService == null) {
6012             Log.w(TAG, "GATT Service is not running!");
6013             return;
6014         }
6015         if (Flags.scanManagerRefactor()) {
6016             mScanController.notifyProfileConnectionStateChange(profile, fromState, toState);
6017         } else {
6018             mGattService.notifyProfileConnectionStateChange(profile, fromState, toState);
6019         }
6020     }
6021 
6022     /**
6023      * Handle Bluetooth app state when connection state changes for a given {@code profile}.
6024      *
6025      * <p>Currently this function is limited to handling Phone policy but the eventual goal is to
6026      * move all connection logic here.
6027      */
handleProfileConnectionStateChange( int profile, BluetoothDevice device, int fromState, int toState)6028     public void handleProfileConnectionStateChange(
6029             int profile, BluetoothDevice device, int fromState, int toState) {
6030         if (mPhonePolicy != null) {
6031             mPhonePolicy.profileConnectionStateChanged(profile, device, fromState, toState);
6032         }
6033     }
6034 
6035     /** Handle Bluetooth app state when active device changes for a given {@code profile}. */
handleActiveDeviceChange(int profile, BluetoothDevice device)6036     public void handleActiveDeviceChange(int profile, BluetoothDevice device) {
6037         mActiveDeviceManager.profileActiveDeviceChanged(profile, device);
6038         mSilenceDeviceManager.profileActiveDeviceChanged(profile, device);
6039         if (mPhonePolicy != null) {
6040             mPhonePolicy.profileActiveDeviceChanged(profile, device);
6041         }
6042     }
6043 
6044     /** Notify MAP and Pbap when a new sdp search record is found. */
sendSdpSearchRecord( BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid)6045     public void sendSdpSearchRecord(
6046             BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) {
6047         if (mMapService != null && mMapService.isAvailable()) {
6048             mMapService.receiveSdpSearchRecord(status, record, uuid);
6049         }
6050         if (mMapClientService != null && mMapClientService.isAvailable()) {
6051             mMapClientService.receiveSdpSearchRecord(device, status, record, uuid);
6052         }
6053         if (mPbapClientService != null && mPbapClientService.isAvailable()) {
6054             mPbapClientService.receiveSdpSearchRecord(device, status, record, uuid);
6055         }
6056     }
6057 
6058     /** Handle Bluetooth profiles when bond state changes with a {@link BluetoothDevice} */
handleBondStateChanged(BluetoothDevice device, int fromState, int toState)6059     public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) {
6060         if (mA2dpService != null && mA2dpService.isAvailable()) {
6061             mA2dpService.handleBondStateChanged(device, fromState, toState);
6062         }
6063         if (mHeadsetService != null && mHeadsetService.isAvailable()) {
6064             mHeadsetService.handleBondStateChanged(device, fromState, toState);
6065         }
6066         if (mLeAudioService != null && mLeAudioService.isAvailable()) {
6067             mLeAudioService.handleBondStateChanged(device, fromState, toState);
6068         }
6069         if (mHearingAidService != null && mHearingAidService.isAvailable()) {
6070             mHearingAidService.handleBondStateChanged(device, fromState, toState);
6071         }
6072         if (mHapClientService != null && mHapClientService.isAvailable()) {
6073             mHapClientService.handleBondStateChanged(device, fromState, toState);
6074         }
6075         if (mBassClientService != null && mBassClientService.isAvailable()) {
6076             mBassClientService.handleBondStateChanged(device, fromState, toState);
6077         }
6078         if (mBatteryService != null && mBatteryService.isAvailable()) {
6079             mBatteryService.handleBondStateChanged(device, fromState, toState);
6080         }
6081         if (mVolumeControlService != null && mVolumeControlService.isAvailable()) {
6082             mVolumeControlService.handleBondStateChanged(device, fromState, toState);
6083         }
6084         if (mPbapService != null && mPbapService.isAvailable()) {
6085             mPbapService.handleBondStateChanged(device, fromState, toState);
6086         }
6087         if (mCsipSetCoordinatorService != null && mCsipSetCoordinatorService.isAvailable()) {
6088             mCsipSetCoordinatorService.handleBondStateChanged(device, fromState, toState);
6089         }
6090         mDatabaseManager.handleBondStateChanged(device, fromState, toState);
6091     }
6092 
convertScanModeToHal(int mode)6093     static int convertScanModeToHal(int mode) {
6094         switch (mode) {
6095             case BluetoothAdapter.SCAN_MODE_NONE:
6096                 return AbstractionLayer.BT_SCAN_MODE_NONE;
6097             case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
6098                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE;
6099             case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
6100                 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
6101         }
6102         // Log.e(TAG, "Incorrect scan mode in convertScanModeToHal");
6103         return -1;
6104     }
6105 
convertScanModeFromHal(int mode)6106     static int convertScanModeFromHal(int mode) {
6107         switch (mode) {
6108             case AbstractionLayer.BT_SCAN_MODE_NONE:
6109                 return BluetoothAdapter.SCAN_MODE_NONE;
6110             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE:
6111                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
6112             case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
6113                 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
6114         }
6115         // Log.e(TAG, "Incorrect scan mode in convertScanModeFromHal");
6116         return -1;
6117     }
6118 
6119     // This function is called from JNI. It allows native code to acquire a single wake lock.
6120     // If the wake lock is already held, this function returns success. Although this function
6121     // only supports acquiring a single wake lock at a time right now, it will eventually be
6122     // extended to allow acquiring an arbitrary number of wake locks. The current interface
6123     // takes |lockName| as a parameter in anticipation of that implementation.
acquireWakeLock(String lockName)6124     boolean acquireWakeLock(String lockName) {
6125         synchronized (this) {
6126             if (mWakeLock == null) {
6127                 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName);
6128             }
6129 
6130             if (!mWakeLock.isHeld()) {
6131                 mWakeLock.acquire();
6132             }
6133         }
6134         return true;
6135     }
6136 
6137     // This function is called from JNI. It allows native code to release a wake lock acquired
6138     // by |acquireWakeLock|. If the wake lock is not held, this function returns failure.
6139     // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is
6140     // needed here. See the comment for |acquireWakeLock| for an explanation of the interface.
releaseWakeLock(String lockName)6141     boolean releaseWakeLock(String lockName) {
6142         synchronized (this) {
6143             if (mWakeLock == null) {
6144                 Log.e(TAG, "Repeated wake lock release; aborting release: " + lockName);
6145                 return false;
6146             }
6147 
6148             if (mWakeLock.isHeld()) {
6149                 mWakeLock.release();
6150             }
6151         }
6152         return true;
6153     }
6154 
energyInfoCallbackInternal( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)6155     void energyInfoCallbackInternal(
6156             int status,
6157             int ctrlState,
6158             long txTime,
6159             long rxTime,
6160             long idleTime,
6161             long energyUsed,
6162             UidTraffic[] data) {
6163         // Energy is product of mA, V and ms. If the chipset doesn't
6164         // report it, we have to compute it from time
6165         if (energyUsed == 0) {
6166             try {
6167                 final long txMah = Math.multiplyExact(txTime, getTxCurrentMa());
6168                 final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa());
6169                 final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa());
6170                 energyUsed =
6171                         (long)
6172                                 (Math.addExact(Math.addExact(txMah, rxMah), idleMah)
6173                                         * getOperatingVolt());
6174             } catch (ArithmeticException e) {
6175                 Log.wtf(TAG, "overflow in bluetooth energy callback", e);
6176                 // Energy is already 0 if the exception was thrown.
6177             }
6178         }
6179 
6180         synchronized (mEnergyInfoLock) {
6181             mStackReportedState = ctrlState;
6182             long totalTxTimeMs;
6183             long totalRxTimeMs;
6184             long totalIdleTimeMs;
6185             long totalEnergy;
6186             try {
6187                 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime);
6188                 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime);
6189                 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime);
6190                 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed);
6191             } catch (ArithmeticException e) {
6192                 // This could be because we accumulated a lot of time, or we got a very strange
6193                 // value from the controller (more likely). Discard this data.
6194                 Log.wtf(TAG, "overflow in bluetooth energy callback", e);
6195                 totalTxTimeMs = mTxTimeTotalMs;
6196                 totalRxTimeMs = mRxTimeTotalMs;
6197                 totalIdleTimeMs = mIdleTimeTotalMs;
6198                 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro;
6199             }
6200 
6201             mTxTimeTotalMs = totalTxTimeMs;
6202             mRxTimeTotalMs = totalRxTimeMs;
6203             mIdleTimeTotalMs = totalIdleTimeMs;
6204             mEnergyUsedTotalVoltAmpSecMicro = totalEnergy;
6205 
6206             for (UidTraffic traffic : data) {
6207                 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid());
6208                 if (existingTraffic == null) {
6209                     mUidTraffic.put(traffic.getUid(), traffic);
6210                 } else {
6211                     existingTraffic.addRxBytes(traffic.getRxBytes());
6212                     existingTraffic.addTxBytes(traffic.getTxBytes());
6213                 }
6214             }
6215             mEnergyInfoLock.notifyAll();
6216         }
6217     }
6218 
energyInfoCallback( int status, int ctrlState, long txTime, long rxTime, long idleTime, long energyUsed, UidTraffic[] data)6219     void energyInfoCallback(
6220             int status,
6221             int ctrlState,
6222             long txTime,
6223             long rxTime,
6224             long idleTime,
6225             long energyUsed,
6226             UidTraffic[] data) {
6227         if (Flags.btSystemContextReport()) {
6228             energyInfoCallbackInternal(
6229                     status, ctrlState, txTime, rxTime, idleTime, energyUsed, data);
6230         } else if (ctrlState >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID
6231                 && ctrlState <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) {
6232             energyInfoCallbackInternal(
6233                     status, ctrlState, txTime, rxTime, idleTime, energyUsed, data);
6234         }
6235         Log.v(
6236                 TAG,
6237                 "energyInfoCallback()"
6238                         + (" status = " + status)
6239                         + (" txTime = " + txTime)
6240                         + (" rxTime = " + rxTime)
6241                         + (" idleTime = " + idleTime)
6242                         + (" energyUsed = " + energyUsed)
6243                         + (" ctrlState = " + String.format("0x%08x", ctrlState))
6244                         + (" traffic = " + Arrays.toString(data)));
6245     }
6246 
6247     /** Update metadata change to registered listeners */
6248     @VisibleForTesting
metadataChanged(String address, int key, byte[] value)6249     public void metadataChanged(String address, int key, byte[] value) {
6250         BluetoothDevice device = mRemoteDevices.getDevice(Utils.getBytesFromAddress(address));
6251 
6252         // pass just interesting metadata to native, to reduce spam
6253         if (key == BluetoothDevice.METADATA_LE_AUDIO) {
6254             mNativeInterface.metadataChanged(Utils.getBytesFromAddress(address), key, value);
6255         }
6256 
6257         if (mMetadataListeners.containsKey(device)) {
6258             List<IBluetoothMetadataListener> list = mMetadataListeners.get(device);
6259             for (IBluetoothMetadataListener listener : list) {
6260                 try {
6261                     listener.onMetadataChanged(device, key, value);
6262                 } catch (RemoteException e) {
6263                     Log.w(TAG, "RemoteException when onMetadataChanged");
6264                 }
6265             }
6266         }
6267     }
6268 
getIdleCurrentMa()6269     private int getIdleCurrentMa() {
6270         return BluetoothProperties.getHardwareIdleCurrentMa().orElse(0);
6271     }
6272 
getTxCurrentMa()6273     private int getTxCurrentMa() {
6274         return BluetoothProperties.getHardwareTxCurrentMa().orElse(0);
6275     }
6276 
getRxCurrentMa()6277     private int getRxCurrentMa() {
6278         return BluetoothProperties.getHardwareRxCurrentMa().orElse(0);
6279     }
6280 
getOperatingVolt()6281     private double getOperatingVolt() {
6282         return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0;
6283     }
6284 
getRemoteDevices()6285     public RemoteDevices getRemoteDevices() {
6286         return mRemoteDevices;
6287     }
6288 
6289     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)6290     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
6291         if (args.length == 0) {
6292             writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section.");
6293             writer.println("Use --print argument for dumpsys direct from AdapterService.");
6294             return;
6295         }
6296 
6297         if ("set-test-mode".equals(args[0])) {
6298             final boolean testModeEnabled = "enabled".equalsIgnoreCase(args[1]);
6299             for (ProfileService profile : mRunningProfiles) {
6300                 profile.setTestModeEnabled(testModeEnabled);
6301             }
6302             mTestModeEnabled = testModeEnabled;
6303             return;
6304         }
6305 
6306         Log.v(TAG, "dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args));
6307         if (args[0].equals("--proto-bin")) {
6308             dumpMetrics(fd);
6309             return;
6310         }
6311 
6312         writer.println();
6313         mAdapterProperties.dump(fd, writer, args);
6314         writer.println("sSnoopLogSettingAtEnable = " + sSnoopLogSettingAtEnable);
6315         writer.println("sDefaultSnoopLogSettingAtEnable = " + sDefaultSnoopLogSettingAtEnable);
6316 
6317         writer.println();
6318         writer.println("Enabled Profile Services:");
6319         for (int profileId : Config.getSupportedProfiles()) {
6320             writer.println("  " + BluetoothProfile.getProfileName(profileId));
6321         }
6322         writer.println();
6323 
6324         mAdapterStateMachine.dump(fd, writer, args);
6325 
6326         StringBuilder sb = new StringBuilder();
6327         for (ProfileService profile : mRegisteredProfiles) {
6328             profile.dump(sb);
6329         }
6330         mSilenceDeviceManager.dump(fd, writer, args);
6331         mDatabaseManager.dump(writer);
6332 
6333         writer.write(sb.toString());
6334         writer.flush();
6335 
6336         final int currentState = mAdapterProperties.getState();
6337         if (currentState == BluetoothAdapter.STATE_OFF
6338                 || currentState == BluetoothAdapter.STATE_BLE_TURNING_ON
6339                 || currentState == BluetoothAdapter.STATE_TURNING_OFF
6340                 || currentState == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
6341             writer.println();
6342             writer.println(
6343                     "Impossible to dump native stack. state="
6344                             + BluetoothAdapter.nameForState(currentState));
6345             writer.println();
6346         } else {
6347             mNativeInterface.dump(fd, args);
6348         }
6349     }
6350 
dumpMetrics(FileDescriptor fd)6351     private void dumpMetrics(FileDescriptor fd) {
6352         BluetoothMetricsProto.BluetoothLog.Builder metricsBuilder =
6353                 BluetoothMetricsProto.BluetoothLog.newBuilder();
6354         byte[] nativeMetricsBytes = mNativeInterface.dumpMetrics();
6355         Log.d(TAG, "dumpMetrics: native metrics size is " + nativeMetricsBytes.length);
6356         if (nativeMetricsBytes.length > 0) {
6357             try {
6358                 metricsBuilder.mergeFrom(nativeMetricsBytes);
6359             } catch (InvalidProtocolBufferException ex) {
6360                 Log.w(TAG, "dumpMetrics: problem parsing metrics protobuf, " + ex.getMessage());
6361                 return;
6362             }
6363         }
6364         metricsBuilder.setNumBondedDevices(getBondedDevices().length);
6365         MetricsLogger.dumpProto(metricsBuilder);
6366         for (ProfileService profile : mRegisteredProfiles) {
6367             profile.dumpProto(metricsBuilder);
6368         }
6369         byte[] metricsBytes = Base64.encode(metricsBuilder.build().toByteArray(), Base64.DEFAULT);
6370         Log.d(TAG, "dumpMetrics: combined metrics size is " + metricsBytes.length);
6371         try (FileOutputStream protoOut = new FileOutputStream(fd)) {
6372             protoOut.write(metricsBytes);
6373         } catch (IOException e) {
6374             Log.e(TAG, "dumpMetrics: error writing combined protobuf to fd, " + e.getMessage());
6375         }
6376     }
6377 
6378     @SuppressLint("AndroidFrameworkRequiresPermission")
enforceBluetoothPrivilegedPermissionIfNeeded( OobData remoteP192Data, OobData remoteP256Data)6379     private void enforceBluetoothPrivilegedPermissionIfNeeded(
6380             OobData remoteP192Data, OobData remoteP256Data) {
6381         if (remoteP192Data != null || remoteP256Data != null) {
6382             enforceBluetoothPrivilegedPermission(this);
6383         }
6384     }
6385 
6386     @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG)
getInitFlags()6387     private String[] getInitFlags() {
6388         final DeviceConfig.Properties properties =
6389                 DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH);
6390         ArrayList<String> initFlags = new ArrayList<>();
6391         for (String property : properties.getKeyset()) {
6392             if (property.startsWith("INIT_")) {
6393                 initFlags.add(
6394                         String.format("%s=%s", property, properties.getString(property, null)));
6395             }
6396         }
6397         return initFlags.toArray(new String[0]);
6398     }
6399 
6400     private final Object mDeviceConfigLock = new Object();
6401 
6402     /**
6403      * Predicate that can be applied to names to determine if a device is well-known to be used for
6404      * physical location.
6405      */
6406     @GuardedBy("mDeviceConfigLock")
6407     private Predicate<String> mLocationDenylistName = (v) -> false;
6408 
6409     /**
6410      * Predicate that can be applied to MAC addresses to determine if a device is well-known to be
6411      * used for physical location.
6412      */
6413     @GuardedBy("mDeviceConfigLock")
6414     private Predicate<byte[]> mLocationDenylistMac = (v) -> false;
6415 
6416     /**
6417      * Predicate that can be applied to Advertising Data payloads to determine if a device is
6418      * well-known to be used for physical location.
6419      */
6420     @GuardedBy("mDeviceConfigLock")
6421     private Predicate<byte[]> mLocationDenylistAdvertisingData = (v) -> false;
6422 
6423     @GuardedBy("mDeviceConfigLock")
6424     private int mScanQuotaCount = DeviceConfigListener.DEFAULT_SCAN_QUOTA_COUNT;
6425 
6426     @GuardedBy("mDeviceConfigLock")
6427     private long mScanQuotaWindowMillis = DeviceConfigListener.DEFAULT_SCAN_QUOTA_WINDOW_MILLIS;
6428 
6429     @GuardedBy("mDeviceConfigLock")
6430     private long mScanTimeoutMillis = DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS;
6431 
6432     @GuardedBy("mDeviceConfigLock")
6433     private int mScanUpgradeDurationMillis =
6434             DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS;
6435 
6436     @GuardedBy("mDeviceConfigLock")
6437     private int mScanDowngradeDurationMillis =
6438             DeviceConfigListener.DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS;
6439 
6440     @GuardedBy("mDeviceConfigLock")
6441     private int mScreenOffLowPowerWindowMillis =
6442             ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS;
6443 
6444     @GuardedBy("mDeviceConfigLock")
6445     private int mScreenOffLowPowerIntervalMillis =
6446             ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS;
6447 
6448     @GuardedBy("mDeviceConfigLock")
6449     private int mScreenOffBalancedWindowMillis =
6450             ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS;
6451 
6452     @GuardedBy("mDeviceConfigLock")
6453     private int mScreenOffBalancedIntervalMillis =
6454             ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS;
6455 
6456     @GuardedBy("mDeviceConfigLock")
6457     private String mLeAudioAllowList;
6458 
getLocationDenylistName()6459     public @NonNull Predicate<String> getLocationDenylistName() {
6460         synchronized (mDeviceConfigLock) {
6461             return mLocationDenylistName;
6462         }
6463     }
6464 
getLocationDenylistMac()6465     public @NonNull Predicate<byte[]> getLocationDenylistMac() {
6466         synchronized (mDeviceConfigLock) {
6467             return mLocationDenylistMac;
6468         }
6469     }
6470 
getLocationDenylistAdvertisingData()6471     public @NonNull Predicate<byte[]> getLocationDenylistAdvertisingData() {
6472         synchronized (mDeviceConfigLock) {
6473             return mLocationDenylistAdvertisingData;
6474         }
6475     }
6476 
6477     /** Returns scan quota count. */
getScanQuotaCount()6478     public int getScanQuotaCount() {
6479         synchronized (mDeviceConfigLock) {
6480             return mScanQuotaCount;
6481         }
6482     }
6483 
6484     /** Returns scan quota window in millis. */
getScanQuotaWindowMillis()6485     public long getScanQuotaWindowMillis() {
6486         synchronized (mDeviceConfigLock) {
6487             return mScanQuotaWindowMillis;
6488         }
6489     }
6490 
6491     /** Returns scan timeout in millis. */
getScanTimeoutMillis()6492     public long getScanTimeoutMillis() {
6493         synchronized (mDeviceConfigLock) {
6494             return mScanTimeoutMillis;
6495         }
6496     }
6497 
6498     /** Returns scan upgrade duration in millis. */
getScanUpgradeDurationMillis()6499     public long getScanUpgradeDurationMillis() {
6500         synchronized (mDeviceConfigLock) {
6501             return mScanUpgradeDurationMillis;
6502         }
6503     }
6504 
6505     /** Returns scan downgrade duration in millis. */
getScanDowngradeDurationMillis()6506     public long getScanDowngradeDurationMillis() {
6507         synchronized (mDeviceConfigLock) {
6508             return mScanDowngradeDurationMillis;
6509         }
6510     }
6511 
6512     /** Returns SCREEN_OFF_BALANCED scan window in millis. */
getScreenOffBalancedWindowMillis()6513     public int getScreenOffBalancedWindowMillis() {
6514         synchronized (mDeviceConfigLock) {
6515             return mScreenOffBalancedWindowMillis;
6516         }
6517     }
6518 
6519     /** Returns SCREEN_OFF_BALANCED scan interval in millis. */
getScreenOffBalancedIntervalMillis()6520     public int getScreenOffBalancedIntervalMillis() {
6521         synchronized (mDeviceConfigLock) {
6522             return mScreenOffBalancedIntervalMillis;
6523         }
6524     }
6525 
6526     /** Returns SCREEN_OFF low power scan window in millis. */
getScreenOffLowPowerWindowMillis()6527     public int getScreenOffLowPowerWindowMillis() {
6528         synchronized (mDeviceConfigLock) {
6529             return mScreenOffLowPowerWindowMillis;
6530         }
6531     }
6532 
6533     /** Returns SCREEN_OFF low power scan interval in millis. */
getScreenOffLowPowerIntervalMillis()6534     public int getScreenOffLowPowerIntervalMillis() {
6535         synchronized (mDeviceConfigLock) {
6536             return mScreenOffLowPowerIntervalMillis;
6537         }
6538     }
6539 
6540     private class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener {
6541         private static final String LOCATION_DENYLIST_NAME = "location_denylist_name";
6542         private static final String LOCATION_DENYLIST_MAC = "location_denylist_mac";
6543         private static final String LOCATION_DENYLIST_ADVERTISING_DATA =
6544                 "location_denylist_advertising_data";
6545         private static final String SCAN_QUOTA_COUNT = "scan_quota_count";
6546         private static final String SCAN_QUOTA_WINDOW_MILLIS = "scan_quota_window_millis";
6547         private static final String SCAN_TIMEOUT_MILLIS = "scan_timeout_millis";
6548         private static final String SCAN_UPGRADE_DURATION_MILLIS = "scan_upgrade_duration_millis";
6549         private static final String SCAN_DOWNGRADE_DURATION_MILLIS =
6550                 "scan_downgrade_duration_millis";
6551         private static final String SCREEN_OFF_LOW_POWER_WINDOW_MILLIS =
6552                 "screen_off_low_power_window_millis";
6553         private static final String SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS =
6554                 "screen_off_low_power_interval_millis";
6555         private static final String SCREEN_OFF_BALANCED_WINDOW_MILLIS =
6556                 "screen_off_balanced_window_millis";
6557         private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS =
6558                 "screen_off_balanced_interval_millis";
6559         private static final String LE_AUDIO_ALLOW_LIST = "le_audio_allow_list";
6560 
6561         /**
6562          * Default denylist which matches Eddystone (except for Eddystone-E2EE-EID) and iBeacon
6563          * payloads.
6564          */
6565         private static final String DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA =
6566                 "⊈0016AAFE40/00FFFFFFF0,⊆0016AAFE/00FFFFFF,⊆00FF4C0002/00FFFFFFFF";
6567 
6568         private static final int DEFAULT_SCAN_QUOTA_COUNT = 5;
6569         private static final long DEFAULT_SCAN_QUOTA_WINDOW_MILLIS = 30 * SECOND_IN_MILLIS;
6570         private static final long DEFAULT_SCAN_TIMEOUT_MILLIS = 10 * MINUTE_IN_MILLIS;
6571         private static final int DEFAULT_SCAN_UPGRADE_DURATION_MILLIS = (int) SECOND_IN_MILLIS * 6;
6572         private static final int DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS =
6573                 (int) SECOND_IN_MILLIS * 6;
6574 
6575         @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG)
start()6576         public void start() {
6577             DeviceConfig.addOnPropertiesChangedListener(
6578                     DeviceConfig.NAMESPACE_BLUETOOTH, BackgroundThread.getExecutor(), this);
6579             onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BLUETOOTH));
6580         }
6581 
6582         @Override
onPropertiesChanged(DeviceConfig.Properties properties)6583         public void onPropertiesChanged(DeviceConfig.Properties properties) {
6584             synchronized (mDeviceConfigLock) {
6585                 final String name = properties.getString(LOCATION_DENYLIST_NAME, null);
6586                 mLocationDenylistName =
6587                         !TextUtils.isEmpty(name)
6588                                 ? Pattern.compile(name).asPredicate()
6589                                 : (v) -> false;
6590                 mLocationDenylistMac =
6591                         BytesMatcher.decode(properties.getString(LOCATION_DENYLIST_MAC, null));
6592                 mLocationDenylistAdvertisingData =
6593                         BytesMatcher.decode(
6594                                 properties.getString(
6595                                         LOCATION_DENYLIST_ADVERTISING_DATA,
6596                                         DEFAULT_LOCATION_DENYLIST_ADVERTISING_DATA));
6597                 mScanQuotaCount = properties.getInt(SCAN_QUOTA_COUNT, DEFAULT_SCAN_QUOTA_COUNT);
6598                 mScanQuotaWindowMillis =
6599                         properties.getLong(
6600                                 SCAN_QUOTA_WINDOW_MILLIS, DEFAULT_SCAN_QUOTA_WINDOW_MILLIS);
6601                 mScanTimeoutMillis =
6602                         properties.getLong(SCAN_TIMEOUT_MILLIS, DEFAULT_SCAN_TIMEOUT_MILLIS);
6603                 mScanUpgradeDurationMillis =
6604                         properties.getInt(
6605                                 SCAN_UPGRADE_DURATION_MILLIS, DEFAULT_SCAN_UPGRADE_DURATION_MILLIS);
6606                 mScanDowngradeDurationMillis =
6607                         properties.getInt(
6608                                 SCAN_DOWNGRADE_DURATION_MILLIS,
6609                                 DEFAULT_SCAN_DOWNGRADE_DURATION_BT_CONNECTING_MILLIS);
6610                 mScreenOffLowPowerWindowMillis =
6611                         properties.getInt(
6612                                 SCREEN_OFF_LOW_POWER_WINDOW_MILLIS,
6613                                 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS);
6614                 mScreenOffLowPowerIntervalMillis =
6615                         properties.getInt(
6616                                 SCREEN_OFF_LOW_POWER_INTERVAL_MILLIS,
6617                                 ScanManager.SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS);
6618                 mScreenOffBalancedWindowMillis =
6619                         properties.getInt(
6620                                 SCREEN_OFF_BALANCED_WINDOW_MILLIS,
6621                                 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS);
6622                 mScreenOffBalancedIntervalMillis =
6623                         properties.getInt(
6624                                 SCREEN_OFF_BALANCED_INTERVAL_MILLIS,
6625                                 ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS);
6626                 mLeAudioAllowList = properties.getString(LE_AUDIO_ALLOW_LIST, "");
6627 
6628                 if (!mLeAudioAllowList.isEmpty()) {
6629                     List<String> leAudioAllowlistFromDeviceConfig =
6630                             Arrays.asList(mLeAudioAllowList.split(","));
6631                     BluetoothProperties.le_audio_allow_list(leAudioAllowlistFromDeviceConfig);
6632                 }
6633 
6634                 List<String> leAudioAllowlistProp = BluetoothProperties.le_audio_allow_list();
6635                 if (leAudioAllowlistProp != null && !leAudioAllowlistProp.isEmpty()) {
6636                     mLeAudioAllowDevices.clear();
6637                     mLeAudioAllowDevices.addAll(leAudioAllowlistProp);
6638                 }
6639             }
6640         }
6641     }
6642 
6643     /** A callback that will be called when AdapterState is changed */
6644     public interface BluetoothStateCallback {
6645         /**
6646          * Called when the status of bluetooth adapter is changing. {@code prevState} and {@code
6647          * newState} takes one of following values defined in BluetoothAdapter.java: STATE_OFF,
6648          * STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON, STATE_BLE_ON,
6649          * STATE_BLE_TURNING_OFF
6650          *
6651          * @param prevState the previous Bluetooth state.
6652          * @param newState the new Bluetooth state.
6653          */
onBluetoothStateChange(int prevState, int newState)6654         void onBluetoothStateChange(int prevState, int newState);
6655     }
6656 
6657     /**
6658      * Obfuscate Bluetooth MAC address into a PII free ID string
6659      *
6660      * @param device Bluetooth device whose MAC address will be obfuscated
6661      * @return a byte array that is unique to this MAC address on this device, or empty byte array
6662      *     when either device is null or obfuscateAddressNative fails
6663      */
obfuscateAddress(BluetoothDevice device)6664     public byte[] obfuscateAddress(BluetoothDevice device) {
6665         if (device == null) {
6666             return new byte[0];
6667         }
6668         return mNativeInterface.obfuscateAddress(Utils.getByteAddress(device));
6669     }
6670 
6671     /**
6672      * Get dynamic audio buffer size supported type
6673      *
6674      * @return support
6675      *     <p>Possible values are {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_NONE}, {@link
6676      *     BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD}, {@link
6677      *     BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}.
6678      */
getDynamicBufferSupport()6679     public int getDynamicBufferSupport() {
6680         return mAdapterProperties.getDynamicBufferSupport();
6681     }
6682 
6683     /**
6684      * Get dynamic audio buffer size
6685      *
6686      * @return BufferConstraints
6687      */
getBufferConstraints()6688     public BufferConstraints getBufferConstraints() {
6689         return mAdapterProperties.getBufferConstraints();
6690     }
6691 
6692     /**
6693      * Set dynamic audio buffer size
6694      *
6695      * @param codec Audio codec
6696      * @param value buffer millis
6697      * @return true if the settings is successful, false otherwise
6698      */
setBufferLengthMillis(int codec, int value)6699     public boolean setBufferLengthMillis(int codec, int value) {
6700         return mAdapterProperties.setBufferLengthMillis(codec, value);
6701     }
6702 
6703     /**
6704      * Get an incremental id of Bluetooth metrics and log
6705      *
6706      * @param device Bluetooth device
6707      * @return int of id for Bluetooth metrics and logging, 0 if the device is invalid
6708      */
getMetricId(BluetoothDevice device)6709     public int getMetricId(BluetoothDevice device) {
6710         if (device == null) {
6711             return 0;
6712         }
6713         return mNativeInterface.getMetricId(Utils.getByteAddress(device));
6714     }
6715 
getCompanionManager()6716     public CompanionManager getCompanionManager() {
6717         return mBtCompanionManager;
6718     }
6719 
6720     /**
6721      * Call for the AdapterService receives bond state change
6722      *
6723      * @param device Bluetooth device
6724      * @param state bond state
6725      */
onBondStateChanged(BluetoothDevice device, int state)6726     public void onBondStateChanged(BluetoothDevice device, int state) {
6727         if (mBtCompanionManager != null) {
6728             mBtCompanionManager.onBondStateChanged(device, state);
6729         }
6730     }
6731 
6732     /**
6733      * Get audio policy feature support status
6734      *
6735      * @param device Bluetooth device to be checked for audio policy support
6736      * @return int status of the remote support for audio policy feature
6737      */
isRequestAudioPolicyAsSinkSupported(BluetoothDevice device)6738     public int isRequestAudioPolicyAsSinkSupported(BluetoothDevice device) {
6739         if (mHeadsetClientService != null) {
6740             return mHeadsetClientService.getAudioPolicyRemoteSupported(device);
6741         } else {
6742             Log.e(TAG, "No audio transport connected");
6743             return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED;
6744         }
6745     }
6746 
6747     /**
6748      * Set audio policy for remote device
6749      *
6750      * @param device Bluetooth device to be set policy for
6751      * @return int result status for requestAudioPolicyAsSink API
6752      */
requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies)6753     public int requestAudioPolicyAsSink(BluetoothDevice device, BluetoothSinkAudioPolicy policies) {
6754         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
6755         if (deviceProp == null) {
6756             return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
6757         }
6758 
6759         if (mHeadsetClientService != null) {
6760             if (isRequestAudioPolicyAsSinkSupported(device)
6761                     != BluetoothStatusCodes.FEATURE_SUPPORTED) {
6762                 throw new UnsupportedOperationException(
6763                         "Request Audio Policy As Sink not supported");
6764             }
6765             deviceProp.setHfAudioPolicyForRemoteAg(policies);
6766             mHeadsetClientService.setAudioPolicy(device, policies);
6767             return BluetoothStatusCodes.SUCCESS;
6768         } else {
6769             Log.e(TAG, "HeadsetClient not connected");
6770             return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
6771         }
6772     }
6773 
6774     /**
6775      * Get audio policy for remote device
6776      *
6777      * @param device Bluetooth device to be set policy for
6778      * @return {@link BluetoothSinkAudioPolicy} policy stored for the device
6779      */
getRequestedAudioPolicyAsSink(BluetoothDevice device)6780     public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(BluetoothDevice device) {
6781         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
6782         if (deviceProp == null) {
6783             return null;
6784         }
6785 
6786         if (mHeadsetClientService != null) {
6787             return deviceProp.getHfAudioPolicyForRemoteAg();
6788         } else {
6789             Log.e(TAG, "HeadsetClient not connected");
6790             return null;
6791         }
6792     }
6793 
6794     /**
6795      * Allow audio low latency
6796      *
6797      * @param allowed true if audio low latency is being allowed
6798      * @param device device whose audio low latency will be allowed or disallowed
6799      * @return boolean true if audio low latency is successfully allowed or disallowed
6800      */
allowLowLatencyAudio(boolean allowed, BluetoothDevice device)6801     public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) {
6802         return mNativeInterface.allowLowLatencyAudio(allowed, Utils.getByteAddress(device));
6803     }
6804 
6805     /**
6806      * get remote PBAP PCE version.
6807      *
6808      * @param address of remote device
6809      * @return int value other than 0 if remote PBAP PCE version is found
6810      */
getRemotePbapPceVersion(String address)6811     public int getRemotePbapPceVersion(String address) {
6812         return mNativeInterface.getRemotePbapPceVersion(address);
6813     }
6814 
6815     /**
6816      * check, if PBAP PSE dynamic version upgrade is enabled.
6817      *
6818      * @return true/false.
6819      */
pbapPseDynamicVersionUpgradeIsEnabled()6820     public boolean pbapPseDynamicVersionUpgradeIsEnabled() {
6821         return mNativeInterface.pbapPseDynamicVersionUpgradeIsEnabled();
6822     }
6823 
6824     /** Sets the battery level of the remote device */
setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas)6825     public void setBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas) {
6826         if (batteryLevel == BATTERY_LEVEL_UNKNOWN) {
6827             mRemoteDevices.resetBatteryLevel(device, isBas);
6828         } else {
6829             mRemoteDevices.updateBatteryLevel(device, batteryLevel, isBas);
6830         }
6831     }
6832 
interopMatchAddr(InteropFeature feature, String address)6833     public boolean interopMatchAddr(InteropFeature feature, String address) {
6834         return mNativeInterface.interopMatchAddr(feature.name(), address);
6835     }
6836 
interopMatchName(InteropFeature feature, String name)6837     public boolean interopMatchName(InteropFeature feature, String name) {
6838         return mNativeInterface.interopMatchName(feature.name(), name);
6839     }
6840 
interopMatchAddrOrName(InteropFeature feature, String address)6841     public boolean interopMatchAddrOrName(InteropFeature feature, String address) {
6842         return mNativeInterface.interopMatchAddrOrName(feature.name(), address);
6843     }
6844 
interopDatabaseAddAddr(InteropFeature feature, String address, int length)6845     public void interopDatabaseAddAddr(InteropFeature feature, String address, int length) {
6846         mNativeInterface.interopDatabaseAddRemoveAddr(true, feature.name(), address, length);
6847     }
6848 
interopDatabaseRemoveAddr(InteropFeature feature, String address)6849     public void interopDatabaseRemoveAddr(InteropFeature feature, String address) {
6850         mNativeInterface.interopDatabaseAddRemoveAddr(false, feature.name(), address, 0);
6851     }
6852 
interopDatabaseAddName(InteropFeature feature, String name)6853     public void interopDatabaseAddName(InteropFeature feature, String name) {
6854         mNativeInterface.interopDatabaseAddRemoveName(true, feature.name(), name);
6855     }
6856 
interopDatabaseRemoveName(InteropFeature feature, String name)6857     public void interopDatabaseRemoveName(InteropFeature feature, String name) {
6858         mNativeInterface.interopDatabaseAddRemoveName(false, feature.name(), name);
6859     }
6860 
6861     /**
6862      * Checks the remote device is in the LE Audio allow list or not.
6863      *
6864      * @param device the device to check
6865      * @return boolean true if the device is in the allow list, false otherwise.
6866      */
isLeAudioAllowed(BluetoothDevice device)6867     public boolean isLeAudioAllowed(BluetoothDevice device) {
6868         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
6869 
6870         if (deviceProp == null
6871                 || deviceProp.getModelName() == null
6872                 || !mLeAudioAllowDevices.contains(deviceProp.getModelName())) {
6873 
6874             return false;
6875         }
6876 
6877         return true;
6878     }
6879 
6880     /**
6881      * Get type of the remote device
6882      *
6883      * @param device the device to check
6884      * @return int device type
6885      */
getRemoteType(BluetoothDevice device)6886     public int getRemoteType(BluetoothDevice device) {
6887         DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
6888         return deviceProp != null
6889                 ? deviceProp.getDeviceType()
6890                 : BluetoothDevice.DEVICE_TYPE_UNKNOWN;
6891     }
6892 
6893     /**
6894      * Sends service discovery UUIDs internally within the stack. This is meant to remove internal
6895      * dependencies on the broadcast {@link BluetoothDevice#ACTION_UUID}.
6896      *
6897      * @param device is the remote device whose UUIDs have been discovered
6898      * @param uuids are the services supported on the remote device
6899      */
sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids)6900     void sendUuidsInternal(BluetoothDevice device, ParcelUuid[] uuids) {
6901         if (device == null) {
6902             Log.w(TAG, "sendUuidsInternal: null device");
6903             return;
6904         }
6905         if (uuids == null) {
6906             Log.w(TAG, "sendUuidsInternal: uuids is null");
6907             return;
6908         }
6909         Log.i(TAG, "sendUuidsInternal: Received service discovery UUIDs for device " + device);
6910         for (int i = 0; i < uuids.length; i++) {
6911             Log.d(TAG, "sendUuidsInternal: index=" + i + " uuid=" + uuids[i]);
6912         }
6913         if (mPhonePolicy != null) {
6914             mPhonePolicy.onUuidsDiscovered(device, uuids);
6915         }
6916     }
6917 
6918     // TODO: b/339548431 delete isMock
6919     // Returns if this is a mock object. This is currently used in testing so that we may not call
6920     // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up
6921     // calling finalize() which in turn calls System.exit() and the process crashes.
6922     //
6923     // Mock this in your testing framework to return true to avoid the mentioned behavior. In
6924     // production this has no effect.
isMock()6925     public boolean isMock() {
6926         return false;
6927     }
6928 }
6929