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