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