AdapterService.java revision e0cda4210b51f608a2c18cd1f128757b60e39222
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 17package com.android.bluetooth.btservice; 18 19import android.app.ActivityManager; 20import android.app.AlarmManager; 21import android.app.PendingIntent; 22import android.app.Service; 23import android.bluetooth.BluetoothActivityEnergyInfo; 24import android.bluetooth.BluetoothAdapter; 25import android.bluetooth.BluetoothClass; 26import android.bluetooth.BluetoothDevice; 27import android.bluetooth.BluetoothProfile; 28import android.bluetooth.IBluetooth; 29import android.bluetooth.IBluetoothCallback; 30import android.bluetooth.IBluetoothSocketManager; 31import android.bluetooth.OobData; 32import android.bluetooth.UidTraffic; 33import android.content.BroadcastReceiver; 34import android.content.Context; 35import android.content.Intent; 36import android.content.IntentFilter; 37import android.content.SharedPreferences; 38import android.content.pm.PackageManager; 39import android.os.AsyncTask; 40import android.os.BatteryStats; 41import android.os.Binder; 42import android.os.Bundle; 43import android.os.Handler; 44import android.os.IBinder; 45import android.os.Looper; 46import android.os.Message; 47import android.os.ParcelUuid; 48import android.os.PowerManager; 49import android.os.Process; 50import android.os.RemoteCallbackList; 51import android.os.RemoteException; 52import android.os.ResultReceiver; 53import android.os.ServiceManager; 54import android.os.SystemClock; 55import android.os.UserHandle; 56import android.os.UserManager; 57import android.provider.Settings; 58import android.text.TextUtils; 59import android.util.Base64; 60import android.util.Log; 61import android.util.Slog; 62import android.util.SparseArray; 63 64import com.android.bluetooth.Utils; 65import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 66import com.android.bluetooth.gatt.GattService; 67import com.android.bluetooth.sdp.SdpManager; 68import com.android.internal.R; 69import com.android.internal.annotations.VisibleForTesting; 70import com.android.internal.app.IBatteryStats; 71 72import java.io.FileDescriptor; 73import java.io.FileOutputStream; 74import java.io.IOException; 75import java.io.PrintWriter; 76import java.nio.charset.StandardCharsets; 77import java.util.ArrayList; 78import java.util.Arrays; 79import java.util.HashMap; 80import java.util.Iterator; 81import java.util.Map; 82 83public class AdapterService extends Service { 84 private static final String TAG = "BluetoothAdapterService"; 85 private static final boolean DBG = true; 86 private static final boolean VERBOSE = false; 87 private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; 88 private static final int MIN_OFFLOADED_FILTERS = 10; 89 private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; 90 91 private final Object mEnergyInfoLock = new Object(); 92 private int mStackReportedState; 93 private long mTxTimeTotalMs; 94 private long mRxTimeTotalMs; 95 private long mIdleTimeTotalMs; 96 private long mEnergyUsedTotalVoltAmpSecMicro; 97 private final SparseArray<UidTraffic> mUidTraffic = new SparseArray<>(); 98 99 private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>(); 100 101 public static final String ACTION_LOAD_ADAPTER_PROPERTIES = 102 "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 103 public static final String ACTION_SERVICE_STATE_CHANGED = 104 "com.android.bluetooth.btservice.action.STATE_CHANGED"; 105 public static final String EXTRA_ACTION = "action"; 106 public static final int PROFILE_CONN_REJECTED = 2; 107 108 private static final String ACTION_ALARM_WAKEUP = 109 "com.android.bluetooth.btservice.action.ALARM_WAKEUP"; 110 111 public static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 112 public static final String BLUETOOTH_PRIVILEGED = 113 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 114 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 115 static final String LOCAL_MAC_ADDRESS_PERM = android.Manifest.permission.LOCAL_MAC_ADDRESS; 116 static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; 117 118 private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = 119 "phonebook_access_permission"; 120 private static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = 121 "message_access_permission"; 122 private static final String SIM_ACCESS_PERMISSION_PREFERENCE_FILE = "sim_access_permission"; 123 124 private static final String[] DEVICE_TYPE_NAMES = new String[]{ 125 "???", "BR/EDR", "LE", "DUAL" 126 }; 127 128 private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; 129 130 static { 131 classInitNative(); 132 } 133 134 private static AdapterService sAdapterService; 135 136 public static synchronized AdapterService getAdapterService() { 137 Log.d(TAG, "getAdapterService() - returning " + sAdapterService); 138 return sAdapterService; 139 } 140 141 private static synchronized void setAdapterService(AdapterService instance) { 142 Log.d(TAG, "setAdapterService() - trying to set service to " + instance); 143 if (instance == null) { 144 return; 145 } 146 sAdapterService = instance; 147 } 148 149 private static synchronized void clearAdapterService(AdapterService current) { 150 if (sAdapterService == current) { 151 sAdapterService = null; 152 } 153 } 154 155 private AdapterProperties mAdapterProperties; 156 private AdapterState mAdapterStateMachine; 157 private BondStateMachine mBondStateMachine; 158 private JniCallbacks mJniCallbacks; 159 private RemoteDevices mRemoteDevices; 160 161 /* TODO: Consider to remove the search API from this class, if changed to use call-back */ 162 private SdpManager mSdpManager = null; 163 164 private boolean mProfilesStarted; 165 private boolean mNativeAvailable; 166 private boolean mCleaningUp; 167 private final HashMap<String, Integer> mProfileServicesState = new HashMap<String, Integer>(); 168 //Only BluetoothManagerService should be registered 169 private RemoteCallbackList<IBluetoothCallback> mCallbacks; 170 private int mCurrentRequestId; 171 private boolean mQuietmode = false; 172 173 private AlarmManager mAlarmManager; 174 private PendingIntent mPendingAlarm; 175 private IBatteryStats mBatteryStats; 176 private PowerManager mPowerManager; 177 private PowerManager.WakeLock mWakeLock; 178 private String mWakeLockName; 179 private UserManager mUserManager; 180 181 private ProfileObserver mProfileObserver; 182 private PhonePolicy mPhonePolicy; 183 private ActiveDeviceManager mActiveDeviceManager; 184 185 public void addProfile(ProfileService profile) { 186 synchronized (mProfiles) { 187 if (!mProfiles.contains(profile)) { 188 mProfiles.add(profile); 189 } 190 } 191 } 192 193 public void removeProfile(ProfileService profile) { 194 synchronized (mProfiles) { 195 mProfiles.remove(profile); 196 } 197 } 198 199 public void onProfileServiceStateChanged(String serviceName, int state) { 200 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 201 m.obj = serviceName; 202 m.arg1 = state; 203 mHandler.sendMessage(m); 204 } 205 206 private void processProfileServiceStateChanged(String serviceName, int state) { 207 boolean doUpdate = false; 208 boolean isBleTurningOn; 209 boolean isBleTurningOff; 210 boolean isTurningOn; 211 boolean isTurningOff; 212 213 synchronized (mProfileServicesState) { 214 Integer prevState = mProfileServicesState.get(serviceName); 215 if (prevState != null && prevState != state) { 216 mProfileServicesState.put(serviceName, state); 217 doUpdate = true; 218 } 219 } 220 221 if (!doUpdate) { 222 return; 223 } 224 225 synchronized (mAdapterStateMachine) { 226 isTurningOff = mAdapterStateMachine.isTurningOff(); 227 isTurningOn = mAdapterStateMachine.isTurningOn(); 228 isBleTurningOn = mAdapterStateMachine.isBleTurningOn(); 229 isBleTurningOff = mAdapterStateMachine.isBleTurningOff(); 230 } 231 232 debugLog( 233 "processProfileServiceStateChanged() - serviceName=" + serviceName + " isTurningOn=" 234 + isTurningOn + " isTurningOff=" + isTurningOff + " isBleTurningOn=" 235 + isBleTurningOn + " isBleTurningOff=" + isBleTurningOff); 236 237 if (isBleTurningOn) { 238 if (GattService.class.getName().equals(serviceName)) { 239 debugLog("GattService is started"); 240 mAdapterStateMachine.sendMessage( 241 mAdapterStateMachine.obtainMessage(AdapterState.BLE_STARTED)); 242 return; 243 } 244 245 } else if (isBleTurningOff) { 246 if (GattService.class.getName().equals(serviceName)) { 247 debugLog("GattService stopped"); 248 mAdapterStateMachine.sendMessage( 249 mAdapterStateMachine.obtainMessage(AdapterState.BLE_STOPPED)); 250 return; 251 } 252 253 } else if (isTurningOff) { 254 //On to BLE_ON 255 //Process stop or disable pending 256 //Check if all services are stopped if so, do cleanup 257 synchronized (mProfileServicesState) { 258 Iterator<Map.Entry<String, Integer>> i = 259 mProfileServicesState.entrySet().iterator(); 260 while (i.hasNext()) { 261 Map.Entry<String, Integer> entry = i.next(); 262 if (GattService.class.getName().equals(entry.getKey())) { 263 continue; 264 } 265 266 if (BluetoothAdapter.STATE_OFF != entry.getValue()) { 267 debugLog("onProfileServiceStateChange() - Profile still running: " 268 + entry.getKey()); 269 return; 270 } 271 } 272 } 273 debugLog("onProfileServiceStateChange() - All profile services stopped..."); 274 //Send message to state machine 275 mProfilesStarted = false; 276 mAdapterStateMachine.sendMessage( 277 mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STOPPED)); 278 279 } else if (isTurningOn) { 280 updateInteropDatabase(); 281 282 //Process start pending 283 //Check if all services are started if so, update state 284 synchronized (mProfileServicesState) { 285 Iterator<Map.Entry<String, Integer>> i = 286 mProfileServicesState.entrySet().iterator(); 287 while (i.hasNext()) { 288 Map.Entry<String, Integer> entry = i.next(); 289 if (GattService.class.getName().equals(entry.getKey())) { 290 continue; 291 } 292 293 if (BluetoothAdapter.STATE_ON != entry.getValue()) { 294 debugLog( 295 "onProfileServiceStateChange() - Profile still not running:" + entry 296 .getKey()); 297 return; 298 } 299 } 300 } 301 debugLog("onProfileServiceStateChange() - All profile services started."); 302 mProfilesStarted = true; 303 //Send message to state machine 304 mAdapterStateMachine.sendMessage( 305 mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 306 } 307 } 308 309 private void updateInteropDatabase() { 310 interopDatabaseClearNative(); 311 312 String interopString = Settings.Global.getString(getContentResolver(), 313 Settings.Global.BLUETOOTH_INTEROPERABILITY_LIST); 314 if (interopString == null) { 315 return; 316 } 317 Log.d(TAG, "updateInteropDatabase: [" + interopString + "]"); 318 319 String[] entries = interopString.split(";"); 320 for (String entry : entries) { 321 String[] tokens = entry.split(","); 322 if (tokens.length != 2) { 323 continue; 324 } 325 326 // Get feature 327 int feature = 0; 328 try { 329 feature = Integer.parseInt(tokens[1]); 330 } catch (NumberFormatException e) { 331 Log.e(TAG, "updateInteropDatabase: Invalid feature '" + tokens[1] + "'"); 332 continue; 333 } 334 335 // Get address bytes and length 336 int length = (tokens[0].length() + 1) / 3; 337 if (length < 1 || length > 6) { 338 Log.e(TAG, "updateInteropDatabase: Malformed address string '" + tokens[0] + "'"); 339 continue; 340 } 341 342 byte[] addr = new byte[6]; 343 int offset = 0; 344 for (int i = 0; i < tokens[0].length(); ) { 345 if (tokens[0].charAt(i) == ':') { 346 i += 1; 347 } else { 348 try { 349 addr[offset++] = (byte) Integer.parseInt(tokens[0].substring(i, i + 2), 16); 350 } catch (NumberFormatException e) { 351 offset = 0; 352 break; 353 } 354 i += 2; 355 } 356 } 357 358 // Check if address was parsed ok, otherwise, move on... 359 if (offset == 0) { 360 continue; 361 } 362 363 // Add entry 364 interopDatabaseAddNative(feature, addr, length); 365 } 366 } 367 368 @Override 369 public void onCreate() { 370 super.onCreate(); 371 debugLog("onCreate()"); 372 mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper()); 373 mRemoteDevices.init(); 374 mBinder = new AdapterServiceBinder(this); 375 mAdapterProperties = new AdapterProperties(this); 376 mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); 377 mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); 378 initNative(); 379 mNativeAvailable = true; 380 mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); 381 //Load the name and address 382 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 383 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 384 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE); 385 mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 386 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 387 mUserManager = (UserManager) getSystemService(Context.USER_SERVICE); 388 mBatteryStats = IBatteryStats.Stub.asInterface( 389 ServiceManager.getService(BatteryStats.SERVICE_NAME)); 390 391 mSdpManager = SdpManager.init(this); 392 registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); 393 mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler()); 394 mProfileObserver.start(); 395 396 // Phone policy is specific to phone implementations and hence if a device wants to exclude 397 // it out then it can be disabled by using the flag below. 398 if (getResources().getBoolean(com.android.bluetooth.R.bool.enable_phone_policy)) { 399 Log.i(TAG, "Phone policy enabled"); 400 mPhonePolicy = new PhonePolicy(this, new ServiceFactory()); 401 mPhonePolicy.start(); 402 } else { 403 Log.i(TAG, "Phone policy disabled"); 404 } 405 406 mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory()); 407 mActiveDeviceManager.start(); 408 409 setAdapterService(this); 410 411 // First call to getSharedPreferences will result in a file read into 412 // memory cache. Call it here asynchronously to avoid potential ANR 413 // in the future 414 new AsyncTask<Void, Void, Void>() { 415 @Override 416 protected Void doInBackground(Void... params) { 417 getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 418 Context.MODE_PRIVATE); 419 getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 420 Context.MODE_PRIVATE); 421 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 422 return null; 423 } 424 }.execute(); 425 426 try { 427 int systemUiUid = getApplicationContext().getPackageManager().getPackageUidAsUser( 428 "com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY, 429 UserHandle.USER_SYSTEM); 430 Utils.setSystemUiUid(systemUiUid); 431 setSystemUiUidNative(systemUiUid); 432 } catch (PackageManager.NameNotFoundException e) { 433 // Some platforms, such as wearables do not have a system ui. 434 Log.w(TAG, "Unable to resolve SystemUI's UID.", e); 435 } 436 437 IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); 438 getApplicationContext().registerReceiverAsUser(sUserSwitchedReceiver, UserHandle.ALL, 439 filter, null, null); 440 int fuid = ActivityManager.getCurrentUser(); 441 Utils.setForegroundUserId(fuid); 442 setForegroundUserIdNative(fuid); 443 } 444 445 @Override 446 public IBinder onBind(Intent intent) { 447 debugLog("onBind()"); 448 return mBinder; 449 } 450 451 @Override 452 public boolean onUnbind(Intent intent) { 453 debugLog("onUnbind() - calling cleanup"); 454 cleanup(); 455 return super.onUnbind(intent); 456 } 457 458 @Override 459 public void onDestroy() { 460 debugLog("onDestroy()"); 461 mProfileObserver.stop(); 462 if (!isMock()) { 463 // TODO(b/27859763) 464 Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack"); 465 System.exit(0); 466 } 467 } 468 469 public static final BroadcastReceiver sUserSwitchedReceiver = new BroadcastReceiver() { 470 @Override 471 public void onReceive(Context context, Intent intent) { 472 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 473 int fuid = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 474 Utils.setForegroundUserId(fuid); 475 setForegroundUserIdNative(fuid); 476 } 477 } 478 }; 479 480 void bleOnProcessStart() { 481 debugLog("bleOnProcessStart()"); 482 483 if (getResources().getBoolean( 484 R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 485 Config.init(getApplicationContext()); 486 } 487 488 Class[] supportedProfileServices = Config.getSupportedProfiles(); 489 //Initialize data objects 490 for (Class service : supportedProfileServices) { 491 mProfileServicesState.put(service.getName(), BluetoothAdapter.STATE_OFF); 492 } 493 494 // Reset |mRemoteDevices| whenever BLE is turned off then on 495 // This is to replace the fact that |mRemoteDevices| was 496 // reinitialized in previous code. 497 // 498 // TODO(apanicke): The reason is unclear but 499 // I believe it is to clear the variable every time BLE was 500 // turned off then on. The same effect can be achieved by 501 // calling cleanup but this may not be necessary at all 502 // We should figure out why this is needed later 503 mRemoteDevices.reset(); 504 mAdapterProperties.init(mRemoteDevices); 505 506 debugLog("bleOnProcessStart() - Make Bond State Machine"); 507 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 508 509 mJniCallbacks.init(mBondStateMachine, mRemoteDevices); 510 511 try { 512 mBatteryStats.noteResetBleScan(); 513 } catch (RemoteException e) { 514 // Ignore. 515 } 516 517 //Start Gatt service 518 setGattProfileServiceState(supportedProfileServices, BluetoothAdapter.STATE_ON); 519 } 520 521 /** 522 * Sets the Bluetooth CoD value of the local adapter if there exists a config value for it. 523 */ 524 void setBluetoothClassFromConfig() { 525 int bluetoothClassConfig = retrieveBluetoothClassConfig(); 526 if (bluetoothClassConfig != 0) { 527 mAdapterProperties.setBluetoothClass(new BluetoothClass(bluetoothClassConfig)); 528 } 529 } 530 531 private int retrieveBluetoothClassConfig() { 532 return Settings.Global.getInt( 533 getContentResolver(), Settings.Global.BLUETOOTH_CLASS_OF_DEVICE, 0); 534 } 535 536 private boolean storeBluetoothClassConfig(int bluetoothClass) { 537 boolean result = Settings.Global.putInt( 538 getContentResolver(), Settings.Global.BLUETOOTH_CLASS_OF_DEVICE, bluetoothClass); 539 540 if (!result) { 541 Log.e(TAG, "Error storing BluetoothClass config - " + bluetoothClass); 542 } 543 544 return result; 545 } 546 547 void startCoreServices() { 548 debugLog("startCoreServices()"); 549 Class[] supportedProfileServices = Config.getSupportedProfiles(); 550 551 //Start profile services 552 if (!mProfilesStarted && supportedProfileServices.length > 0 553 && !(supportedProfileServices.length == 1 554 && supportedProfileServices[0] == GattService.class)) { 555 //Startup all profile services 556 setProfileServiceState(supportedProfileServices, BluetoothAdapter.STATE_ON); 557 } else { 558 debugLog("startCoreProfiles(): Profile Services alreay started"); 559 mAdapterStateMachine.sendMessage( 560 mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 561 } 562 } 563 564 void startBluetoothDisable() { 565 mAdapterStateMachine.sendMessage( 566 mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE)); 567 } 568 569 boolean stopProfileServices() { 570 Class[] supportedProfileServices = Config.getSupportedProfiles(); 571 if (mProfilesStarted && supportedProfileServices.length > 0) { 572 setProfileServiceState(supportedProfileServices, BluetoothAdapter.STATE_OFF); 573 return true; 574 } 575 debugLog("stopProfileServices() - No profiles services to stop or already stopped."); 576 return false; 577 } 578 579 boolean stopGattProfileService() { 580 //TODO: can optimize this instead of looping around all supported profiles 581 debugLog("stopGattProfileService()"); 582 Class[] supportedProfileServices = Config.getSupportedProfiles(); 583 584 setGattProfileServiceState(supportedProfileServices, BluetoothAdapter.STATE_OFF); 585 return true; 586 } 587 588 589 void updateAdapterState(int prevState, int newState) { 590 if (mCallbacks != null) { 591 int n = mCallbacks.beginBroadcast(); 592 debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 593 for (int i = 0; i < n; i++) { 594 try { 595 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState); 596 } catch (RemoteException e) { 597 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 598 } 599 } 600 mCallbacks.finishBroadcast(); 601 } 602 } 603 604 void cleanup() { 605 debugLog("cleanup()"); 606 if (mCleaningUp) { 607 errorLog("cleanup() - Service already starting to cleanup, ignoring request..."); 608 return; 609 } 610 611 clearAdapterService(this); 612 613 mCleaningUp = true; 614 615 unregisterReceiver(mAlarmBroadcastReceiver); 616 617 if (mPendingAlarm != null) { 618 mAlarmManager.cancel(mPendingAlarm); 619 mPendingAlarm = null; 620 } 621 622 // This wake lock release may also be called concurrently by 623 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 624 synchronized (this) { 625 if (mWakeLock != null) { 626 if (mWakeLock.isHeld()) { 627 mWakeLock.release(); 628 } 629 mWakeLock = null; 630 } 631 } 632 633 if (mAdapterStateMachine != null) { 634 mAdapterStateMachine.doQuit(); 635 } 636 637 if (mBondStateMachine != null) { 638 mBondStateMachine.doQuit(); 639 } 640 641 if (mRemoteDevices != null) { 642 mRemoteDevices.cleanup(); 643 } 644 645 if (mSdpManager != null) { 646 mSdpManager.cleanup(); 647 mSdpManager = null; 648 } 649 650 if (mNativeAvailable) { 651 debugLog("cleanup() - Cleaning up adapter native"); 652 cleanupNative(); 653 mNativeAvailable = false; 654 } 655 656 if (mAdapterProperties != null) { 657 mAdapterProperties.cleanup(); 658 } 659 660 if (mJniCallbacks != null) { 661 mJniCallbacks.cleanup(); 662 } 663 664 if (mPhonePolicy != null) { 665 mPhonePolicy.cleanup(); 666 } 667 668 if (mActiveDeviceManager != null) { 669 mActiveDeviceManager.cleanup(); 670 } 671 672 if (mProfileServicesState != null) { 673 mProfileServicesState.clear(); 674 } 675 676 if (mBinder != null) { 677 mBinder.cleanup(); 678 mBinder = null; //Do not remove. Otherwise Binder leak! 679 } 680 681 if (mCallbacks != null) { 682 mCallbacks.kill(); 683 } 684 } 685 686 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1; 687 688 private final Handler mHandler = new Handler() { 689 @Override 690 public void handleMessage(Message msg) { 691 debugLog("handleMessage() - Message: " + msg.what); 692 693 switch (msg.what) { 694 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 695 debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 696 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 697 } 698 break; 699 } 700 } 701 }; 702 703 @SuppressWarnings("rawtypes") 704 private void setGattProfileServiceState(Class[] services, int state) { 705 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 706 Log.w(TAG, "setGattProfileServiceState(): invalid state...Leaving..."); 707 return; 708 } 709 710 int expectedCurrentState = BluetoothAdapter.STATE_OFF; 711 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 712 713 if (state == BluetoothAdapter.STATE_OFF) { 714 expectedCurrentState = BluetoothAdapter.STATE_ON; 715 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 716 } 717 718 for (Class service : services) { 719 String serviceName = service.getName(); 720 String simpleName = service.getSimpleName(); 721 722 if (GattService.class.getSimpleName().equals(simpleName)) { 723 Integer serviceState = mProfileServicesState.get(serviceName); 724 725 if (serviceState != null && serviceState != expectedCurrentState) { 726 debugLog("setProfileServiceState() - Unable to " + ( 727 state == BluetoothAdapter.STATE_OFF ? "start" : "stop") + " service " 728 + serviceName + ". Invalid state: " + serviceState); 729 continue; 730 } 731 debugLog("setProfileServiceState() - " + (state == BluetoothAdapter.STATE_OFF 732 ? "Stopping" : "Starting") + " service " + serviceName); 733 734 mProfileServicesState.put(serviceName, pendingState); 735 Intent intent = new Intent(this, service); 736 intent.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 737 intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 738 startService(intent); 739 return; 740 } 741 } 742 } 743 744 745 @SuppressWarnings("rawtypes") 746 private void setProfileServiceState(Class[] services, int state) { 747 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 748 debugLog("setProfileServiceState() - Invalid state, leaving..."); 749 return; 750 } 751 752 int expectedCurrentState = BluetoothAdapter.STATE_OFF; 753 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 754 if (state == BluetoothAdapter.STATE_OFF) { 755 expectedCurrentState = BluetoothAdapter.STATE_ON; 756 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 757 } 758 759 for (Class service : services) { 760 String serviceName = service.getName(); 761 String simpleName = service.getSimpleName(); 762 763 if (GattService.class.getSimpleName().equals(simpleName)) { 764 continue; 765 } 766 767 Integer serviceState = mProfileServicesState.get(serviceName); 768 if (serviceState != null && serviceState != expectedCurrentState) { 769 debugLog("setProfileServiceState() - Unable to " + ( 770 state == BluetoothAdapter.STATE_OFF ? "start" : "stop") + " service " 771 + serviceName + ". Invalid state: " + serviceState); 772 continue; 773 } 774 775 debugLog("setProfileServiceState() - " + (state == BluetoothAdapter.STATE_OFF 776 ? "Stopping" : "Starting") + " service " + serviceName); 777 778 mProfileServicesState.put(serviceName, pendingState); 779 Intent intent = new Intent(this, service); 780 intent.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 781 intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 782 startService(intent); 783 } 784 } 785 786 private boolean isAvailable() { 787 return !mCleaningUp; 788 } 789 790 /** 791 * Handlers for incoming service calls 792 */ 793 private AdapterServiceBinder mBinder; 794 795 /** 796 * The Binder implementation must be declared to be a static class, with 797 * the AdapterService instance passed in the constructor. Furthermore, 798 * when the AdapterService shuts down, the reference to the AdapterService 799 * must be explicitly removed. 800 * 801 * Otherwise, a memory leak can occur from repeated starting/stopping the 802 * service...Please refer to android.os.Binder for further details on 803 * why an inner instance class should be avoided. 804 * 805 */ 806 private static class AdapterServiceBinder extends IBluetooth.Stub { 807 private AdapterService mService; 808 809 AdapterServiceBinder(AdapterService svc) { 810 mService = svc; 811 } 812 813 public void cleanup() { 814 mService = null; 815 } 816 817 public AdapterService getService() { 818 if (mService != null && mService.isAvailable()) { 819 return mService; 820 } 821 return null; 822 } 823 824 @Override 825 public boolean isEnabled() { 826 // don't check caller, may be called from system UI 827 AdapterService service = getService(); 828 if (service == null) { 829 return false; 830 } 831 return service.isEnabled(); 832 } 833 834 @Override 835 public int getState() { 836 // don't check caller, may be called from system UI 837 AdapterService service = getService(); 838 if (service == null) { 839 return BluetoothAdapter.STATE_OFF; 840 } 841 return service.getState(); 842 } 843 844 @Override 845 public boolean enable() { 846 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) { 847 Log.w(TAG, "enable() - Not allowed for non-active user and non system user"); 848 return false; 849 } 850 AdapterService service = getService(); 851 if (service == null) { 852 return false; 853 } 854 return service.enable(); 855 } 856 857 @Override 858 public boolean enableNoAutoConnect() { 859 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) { 860 Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user"); 861 return false; 862 } 863 864 AdapterService service = getService(); 865 if (service == null) { 866 return false; 867 } 868 return service.enableNoAutoConnect(); 869 } 870 871 @Override 872 public boolean disable() { 873 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) { 874 Log.w(TAG, "disable() - Not allowed for non-active user and non system user"); 875 return false; 876 } 877 878 AdapterService service = getService(); 879 if (service == null) { 880 return false; 881 } 882 return service.disable(); 883 } 884 885 @Override 886 public String getAddress() { 887 if ((Binder.getCallingUid() != Process.SYSTEM_UID) 888 && (!Utils.checkCallerAllowManagedProfiles(mService))) { 889 Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user"); 890 return null; 891 } 892 893 AdapterService service = getService(); 894 if (service == null) { 895 return null; 896 } 897 return service.getAddress(); 898 } 899 900 @Override 901 public ParcelUuid[] getUuids() { 902 if (!Utils.checkCaller()) { 903 Log.w(TAG, "getUuids() - Not allowed for non-active user"); 904 return new ParcelUuid[0]; 905 } 906 907 AdapterService service = getService(); 908 if (service == null) { 909 return new ParcelUuid[0]; 910 } 911 return service.getUuids(); 912 } 913 914 @Override 915 public String getName() { 916 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) { 917 Log.w(TAG, "getName() - Not allowed for non-active user and non system user"); 918 return null; 919 } 920 921 AdapterService service = getService(); 922 if (service == null) { 923 return null; 924 } 925 return service.getName(); 926 } 927 928 @Override 929 public boolean setName(String name) { 930 if (!Utils.checkCaller()) { 931 Log.w(TAG, "setName() - Not allowed for non-active user"); 932 return false; 933 } 934 935 AdapterService service = getService(); 936 if (service == null) { 937 return false; 938 } 939 return service.setName(name); 940 } 941 942 public BluetoothClass getBluetoothClass() { 943 if (!Utils.checkCaller()) { 944 Log.w(TAG, "getBluetoothClass() - Not allowed for non-active user"); 945 return null; 946 } 947 948 AdapterService service = getService(); 949 if (service == null) return null; 950 return service.getBluetoothClass(); 951 } 952 953 public boolean setBluetoothClass(BluetoothClass bluetoothClass) { 954 if (!Utils.checkCaller()) { 955 Log.w(TAG, "setBluetoothClass() - Not allowed for non-active user"); 956 return false; 957 } 958 959 AdapterService service = getService(); 960 if (service == null) { 961 return false; 962 } 963 return service.setBluetoothClass(bluetoothClass); 964 } 965 966 @Override 967 public int getScanMode() { 968 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 969 Log.w(TAG, "getScanMode() - Not allowed for non-active user"); 970 return BluetoothAdapter.SCAN_MODE_NONE; 971 } 972 973 AdapterService service = getService(); 974 if (service == null) { 975 return BluetoothAdapter.SCAN_MODE_NONE; 976 } 977 return service.getScanMode(); 978 } 979 980 @Override 981 public boolean setScanMode(int mode, int duration) { 982 if (!Utils.checkCaller()) { 983 Log.w(TAG, "setScanMode() - Not allowed for non-active user"); 984 return false; 985 } 986 987 AdapterService service = getService(); 988 if (service == null) { 989 return false; 990 } 991 return service.setScanMode(mode, duration); 992 } 993 994 @Override 995 public int getDiscoverableTimeout() { 996 if (!Utils.checkCaller()) { 997 Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user"); 998 return 0; 999 } 1000 1001 AdapterService service = getService(); 1002 if (service == null) { 1003 return 0; 1004 } 1005 return service.getDiscoverableTimeout(); 1006 } 1007 1008 @Override 1009 public boolean setDiscoverableTimeout(int timeout) { 1010 if (!Utils.checkCaller()) { 1011 Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user"); 1012 return false; 1013 } 1014 1015 AdapterService service = getService(); 1016 if (service == null) { 1017 return false; 1018 } 1019 return service.setDiscoverableTimeout(timeout); 1020 } 1021 1022 @Override 1023 public boolean startDiscovery() { 1024 if (!Utils.checkCaller()) { 1025 Log.w(TAG, "startDiscovery() - Not allowed for non-active user"); 1026 return false; 1027 } 1028 1029 AdapterService service = getService(); 1030 if (service == null) { 1031 return false; 1032 } 1033 return service.startDiscovery(); 1034 } 1035 1036 @Override 1037 public boolean cancelDiscovery() { 1038 if (!Utils.checkCaller()) { 1039 Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user"); 1040 return false; 1041 } 1042 1043 AdapterService service = getService(); 1044 if (service == null) { 1045 return false; 1046 } 1047 return service.cancelDiscovery(); 1048 } 1049 1050 @Override 1051 public boolean isDiscovering() { 1052 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1053 Log.w(TAG, "isDiscovering() - Not allowed for non-active user"); 1054 return false; 1055 } 1056 1057 AdapterService service = getService(); 1058 if (service == null) { 1059 return false; 1060 } 1061 return service.isDiscovering(); 1062 } 1063 1064 @Override 1065 public long getDiscoveryEndMillis() { 1066 if (!Utils.checkCaller()) { 1067 Log.w(TAG, "getDiscoveryEndMillis() - Not allowed for non-active user"); 1068 return -1; 1069 } 1070 1071 AdapterService service = getService(); 1072 if (service == null) { 1073 return -1; 1074 } 1075 return service.getDiscoveryEndMillis(); 1076 } 1077 1078 @Override 1079 public BluetoothDevice[] getBondedDevices() { 1080 // don't check caller, may be called from system UI 1081 AdapterService service = getService(); 1082 if (service == null) { 1083 return new BluetoothDevice[0]; 1084 } 1085 return service.getBondedDevices(); 1086 } 1087 1088 @Override 1089 public int getAdapterConnectionState() { 1090 // don't check caller, may be called from system UI 1091 AdapterService service = getService(); 1092 if (service == null) { 1093 return BluetoothAdapter.STATE_DISCONNECTED; 1094 } 1095 return service.getAdapterConnectionState(); 1096 } 1097 1098 @Override 1099 public int getProfileConnectionState(int profile) { 1100 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1101 Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user"); 1102 return BluetoothProfile.STATE_DISCONNECTED; 1103 } 1104 1105 AdapterService service = getService(); 1106 if (service == null) { 1107 return BluetoothProfile.STATE_DISCONNECTED; 1108 } 1109 return service.getProfileConnectionState(profile); 1110 } 1111 1112 @Override 1113 public boolean createBond(BluetoothDevice device, int transport) { 1114 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1115 Log.w(TAG, "createBond() - Not allowed for non-active user"); 1116 return false; 1117 } 1118 1119 AdapterService service = getService(); 1120 if (service == null) { 1121 return false; 1122 } 1123 return service.createBond(device, transport, null); 1124 } 1125 1126 @Override 1127 public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) { 1128 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1129 Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user"); 1130 return false; 1131 } 1132 1133 AdapterService service = getService(); 1134 if (service == null) { 1135 return false; 1136 } 1137 return service.createBond(device, transport, oobData); 1138 } 1139 1140 @Override 1141 public boolean cancelBondProcess(BluetoothDevice device) { 1142 if (!Utils.checkCaller()) { 1143 Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user"); 1144 return false; 1145 } 1146 1147 AdapterService service = getService(); 1148 if (service == null) { 1149 return false; 1150 } 1151 return service.cancelBondProcess(device); 1152 } 1153 1154 @Override 1155 public boolean removeBond(BluetoothDevice device) { 1156 if (!Utils.checkCaller()) { 1157 Log.w(TAG, "removeBond() - Not allowed for non-active user"); 1158 return false; 1159 } 1160 1161 AdapterService service = getService(); 1162 if (service == null) { 1163 return false; 1164 } 1165 return service.removeBond(device); 1166 } 1167 1168 @Override 1169 public int getBondState(BluetoothDevice device) { 1170 // don't check caller, may be called from system UI 1171 AdapterService service = getService(); 1172 if (service == null) { 1173 return BluetoothDevice.BOND_NONE; 1174 } 1175 return service.getBondState(device); 1176 } 1177 1178 @Override 1179 public boolean isBondingInitiatedLocally(BluetoothDevice device) { 1180 // don't check caller, may be called from system UI 1181 AdapterService service = getService(); 1182 if (service == null) { 1183 return false; 1184 } 1185 return service.isBondingInitiatedLocally(device); 1186 } 1187 1188 @Override 1189 public long getSupportedProfiles() { 1190 AdapterService service = getService(); 1191 if (service == null) { 1192 return 0; 1193 } 1194 return service.getSupportedProfiles(); 1195 } 1196 1197 @Override 1198 public int getConnectionState(BluetoothDevice device) { 1199 AdapterService service = getService(); 1200 if (service == null) { 1201 return 0; 1202 } 1203 return service.getConnectionState(device); 1204 } 1205 1206 @Override 1207 public String getRemoteName(BluetoothDevice device) { 1208 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1209 Log.w(TAG, "getRemoteName() - Not allowed for non-active user"); 1210 return null; 1211 } 1212 1213 AdapterService service = getService(); 1214 if (service == null) { 1215 return null; 1216 } 1217 return service.getRemoteName(device); 1218 } 1219 1220 @Override 1221 public int getRemoteType(BluetoothDevice device) { 1222 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1223 Log.w(TAG, "getRemoteType() - Not allowed for non-active user"); 1224 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1225 } 1226 1227 AdapterService service = getService(); 1228 if (service == null) { 1229 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1230 } 1231 return service.getRemoteType(device); 1232 } 1233 1234 @Override 1235 public String getRemoteAlias(BluetoothDevice device) { 1236 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1237 Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user"); 1238 return null; 1239 } 1240 1241 AdapterService service = getService(); 1242 if (service == null) { 1243 return null; 1244 } 1245 return service.getRemoteAlias(device); 1246 } 1247 1248 @Override 1249 public boolean setRemoteAlias(BluetoothDevice device, String name) { 1250 if (!Utils.checkCaller()) { 1251 Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user"); 1252 return false; 1253 } 1254 1255 AdapterService service = getService(); 1256 if (service == null) { 1257 return false; 1258 } 1259 return service.setRemoteAlias(device, name); 1260 } 1261 1262 @Override 1263 public int getRemoteClass(BluetoothDevice device) { 1264 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1265 Log.w(TAG, "getRemoteClass() - Not allowed for non-active user"); 1266 return 0; 1267 } 1268 1269 AdapterService service = getService(); 1270 if (service == null) { 1271 return 0; 1272 } 1273 return service.getRemoteClass(device); 1274 } 1275 1276 @Override 1277 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1278 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1279 Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user"); 1280 return new ParcelUuid[0]; 1281 } 1282 1283 AdapterService service = getService(); 1284 if (service == null) { 1285 return new ParcelUuid[0]; 1286 } 1287 return service.getRemoteUuids(device); 1288 } 1289 1290 @Override 1291 public boolean fetchRemoteUuids(BluetoothDevice device) { 1292 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1293 Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user"); 1294 return false; 1295 } 1296 1297 AdapterService service = getService(); 1298 if (service == null) { 1299 return false; 1300 } 1301 return service.fetchRemoteUuids(device); 1302 } 1303 1304 1305 @Override 1306 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1307 if (!Utils.checkCaller()) { 1308 Log.w(TAG, "setPin() - Not allowed for non-active user"); 1309 return false; 1310 } 1311 1312 AdapterService service = getService(); 1313 if (service == null) { 1314 return false; 1315 } 1316 return service.setPin(device, accept, len, pinCode); 1317 } 1318 1319 @Override 1320 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1321 if (!Utils.checkCaller()) { 1322 Log.w(TAG, "setPasskey() - Not allowed for non-active user"); 1323 return false; 1324 } 1325 1326 AdapterService service = getService(); 1327 if (service == null) { 1328 return false; 1329 } 1330 return service.setPasskey(device, accept, len, passkey); 1331 } 1332 1333 @Override 1334 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1335 if (!Utils.checkCaller()) { 1336 Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user"); 1337 return false; 1338 } 1339 1340 AdapterService service = getService(); 1341 if (service == null) { 1342 return false; 1343 } 1344 return service.setPairingConfirmation(device, accept); 1345 } 1346 1347 @Override 1348 public int getPhonebookAccessPermission(BluetoothDevice device) { 1349 if (!Utils.checkCaller()) { 1350 Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user"); 1351 return BluetoothDevice.ACCESS_UNKNOWN; 1352 } 1353 1354 AdapterService service = getService(); 1355 if (service == null) { 1356 return BluetoothDevice.ACCESS_UNKNOWN; 1357 } 1358 return service.getPhonebookAccessPermission(device); 1359 } 1360 1361 @Override 1362 public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1363 if (!Utils.checkCaller()) { 1364 Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user"); 1365 return false; 1366 } 1367 1368 AdapterService service = getService(); 1369 if (service == null) { 1370 return false; 1371 } 1372 return service.setPhonebookAccessPermission(device, value); 1373 } 1374 1375 @Override 1376 public int getMessageAccessPermission(BluetoothDevice device) { 1377 if (!Utils.checkCaller()) { 1378 Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user"); 1379 return BluetoothDevice.ACCESS_UNKNOWN; 1380 } 1381 1382 AdapterService service = getService(); 1383 if (service == null) { 1384 return BluetoothDevice.ACCESS_UNKNOWN; 1385 } 1386 return service.getMessageAccessPermission(device); 1387 } 1388 1389 @Override 1390 public boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1391 if (!Utils.checkCaller()) { 1392 Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user"); 1393 return false; 1394 } 1395 1396 AdapterService service = getService(); 1397 if (service == null) { 1398 return false; 1399 } 1400 return service.setMessageAccessPermission(device, value); 1401 } 1402 1403 @Override 1404 public int getSimAccessPermission(BluetoothDevice device) { 1405 if (!Utils.checkCaller()) { 1406 Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user"); 1407 return BluetoothDevice.ACCESS_UNKNOWN; 1408 } 1409 1410 AdapterService service = getService(); 1411 if (service == null) { 1412 return BluetoothDevice.ACCESS_UNKNOWN; 1413 } 1414 return service.getSimAccessPermission(device); 1415 } 1416 1417 @Override 1418 public boolean setSimAccessPermission(BluetoothDevice device, int value) { 1419 if (!Utils.checkCaller()) { 1420 Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user"); 1421 return false; 1422 } 1423 1424 AdapterService service = getService(); 1425 if (service == null) { 1426 return false; 1427 } 1428 return service.setSimAccessPermission(device, value); 1429 } 1430 1431 @Override 1432 public void sendConnectionStateChange(BluetoothDevice device, int profile, int state, 1433 int prevState) { 1434 AdapterService service = getService(); 1435 if (service == null) { 1436 return; 1437 } 1438 service.sendConnectionStateChange(device, profile, state, prevState); 1439 } 1440 1441 @Override 1442 public IBluetoothSocketManager getSocketManager() { 1443 AdapterService service = getService(); 1444 if (service == null) { 1445 return null; 1446 } 1447 return service.getSocketManager(); 1448 } 1449 1450 @Override 1451 public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { 1452 if (!Utils.checkCaller()) { 1453 Log.w(TAG, "sdpSea(): not allowed for non-active user"); 1454 return false; 1455 } 1456 1457 AdapterService service = getService(); 1458 if (service == null) { 1459 return false; 1460 } 1461 return service.sdpSearch(device, uuid); 1462 } 1463 1464 @Override 1465 public int getBatteryLevel(BluetoothDevice device) { 1466 if (!Utils.checkCaller()) { 1467 Log.w(TAG, "getBatteryLevel(): not allowed for non-active user"); 1468 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 1469 } 1470 1471 AdapterService service = getService(); 1472 if (service == null) { 1473 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 1474 } 1475 return service.getBatteryLevel(device); 1476 } 1477 1478 @Override 1479 public int getMaxConnectedAudioDevices() { 1480 // don't check caller, may be called from system UI 1481 AdapterService service = getService(); 1482 if (service == null) { 1483 return AdapterProperties.MIN_CONNECTED_AUDIO_DEVICES; 1484 } 1485 return service.getMaxConnectedAudioDevices(); 1486 } 1487 1488 @Override 1489 public boolean factoryReset() { 1490 AdapterService service = getService(); 1491 if (service == null) { 1492 return false; 1493 } 1494 service.disable(); 1495 return service.factoryReset(); 1496 1497 } 1498 1499 @Override 1500 public void registerCallback(IBluetoothCallback cb) { 1501 AdapterService service = getService(); 1502 if (service == null) { 1503 return; 1504 } 1505 service.registerCallback(cb); 1506 } 1507 1508 @Override 1509 public void unregisterCallback(IBluetoothCallback cb) { 1510 AdapterService service = getService(); 1511 if (service == null) { 1512 return; 1513 } 1514 service.unregisterCallback(cb); 1515 } 1516 1517 @Override 1518 public boolean isMultiAdvertisementSupported() { 1519 AdapterService service = getService(); 1520 if (service == null) { 1521 return false; 1522 } 1523 return service.isMultiAdvertisementSupported(); 1524 } 1525 1526 @Override 1527 public boolean isOffloadedFilteringSupported() { 1528 AdapterService service = getService(); 1529 if (service == null) { 1530 return false; 1531 } 1532 int val = service.getNumOfOffloadedScanFilterSupported(); 1533 return (val >= MIN_OFFLOADED_FILTERS); 1534 } 1535 1536 @Override 1537 public boolean isOffloadedScanBatchingSupported() { 1538 AdapterService service = getService(); 1539 if (service == null) { 1540 return false; 1541 } 1542 int val = service.getOffloadedScanResultStorage(); 1543 return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES); 1544 } 1545 1546 @Override 1547 public boolean isLe2MPhySupported() { 1548 AdapterService service = getService(); 1549 if (service == null) { 1550 return false; 1551 } 1552 return service.isLe2MPhySupported(); 1553 } 1554 1555 @Override 1556 public boolean isLeCodedPhySupported() { 1557 AdapterService service = getService(); 1558 if (service == null) { 1559 return false; 1560 } 1561 return service.isLeCodedPhySupported(); 1562 } 1563 1564 @Override 1565 public boolean isLeExtendedAdvertisingSupported() { 1566 AdapterService service = getService(); 1567 if (service == null) { 1568 return false; 1569 } 1570 return service.isLeExtendedAdvertisingSupported(); 1571 } 1572 1573 @Override 1574 public boolean isLePeriodicAdvertisingSupported() { 1575 AdapterService service = getService(); 1576 if (service == null) { 1577 return false; 1578 } 1579 return service.isLePeriodicAdvertisingSupported(); 1580 } 1581 1582 @Override 1583 public int getLeMaximumAdvertisingDataLength() { 1584 AdapterService service = getService(); 1585 if (service == null) { 1586 return 0; 1587 } 1588 return service.getLeMaximumAdvertisingDataLength(); 1589 } 1590 1591 @Override 1592 public boolean isActivityAndEnergyReportingSupported() { 1593 AdapterService service = getService(); 1594 if (service == null) { 1595 return false; 1596 } 1597 return service.isActivityAndEnergyReportingSupported(); 1598 } 1599 1600 @Override 1601 public BluetoothActivityEnergyInfo reportActivityInfo() { 1602 AdapterService service = getService(); 1603 if (service == null) { 1604 return null; 1605 } 1606 return service.reportActivityInfo(); 1607 } 1608 1609 @Override 1610 public void requestActivityInfo(ResultReceiver result) { 1611 Bundle bundle = new Bundle(); 1612 bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, reportActivityInfo()); 1613 result.send(0, bundle); 1614 } 1615 1616 @Override 1617 public void onLeServiceUp() { 1618 AdapterService service = getService(); 1619 if (service == null) { 1620 return; 1621 } 1622 service.onLeServiceUp(); 1623 } 1624 1625 @Override 1626 public void onBrEdrDown() { 1627 AdapterService service = getService(); 1628 if (service == null) { 1629 return; 1630 } 1631 service.onBrEdrDown(); 1632 } 1633 1634 @Override 1635 public void dump(FileDescriptor fd, String[] args) { 1636 PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); 1637 AdapterService service = getService(); 1638 if (service == null) { 1639 return; 1640 } 1641 service.dump(fd, writer, args); 1642 } 1643 } 1644 1645 ; 1646 1647 // ----API Methods-------- 1648 1649 public boolean isEnabled() { 1650 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1651 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 1652 } 1653 1654 public int getState() { 1655 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1656 if (mAdapterProperties != null) { 1657 return mAdapterProperties.getState(); 1658 } 1659 return BluetoothAdapter.STATE_OFF; 1660 } 1661 1662 public boolean enable() { 1663 return enable(false); 1664 } 1665 1666 public boolean enableNoAutoConnect() { 1667 return enable(true); 1668 } 1669 1670 public synchronized boolean enable(boolean quietMode) { 1671 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1672 1673 // Enforce the user restriction for disallowing Bluetooth if it was set. 1674 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) { 1675 debugLog("enable() called when Bluetooth was disallowed"); 1676 return false; 1677 } 1678 1679 debugLog("enable() - Enable called with quiet mode status = " + quietMode); 1680 mQuietmode = quietMode; 1681 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON); 1682 mAdapterStateMachine.sendMessage(m); 1683 return true; 1684 } 1685 1686 boolean disable() { 1687 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1688 1689 debugLog("disable() called..."); 1690 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF); 1691 mAdapterStateMachine.sendMessage(m); 1692 return true; 1693 } 1694 1695 String getAddress() { 1696 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1697 enforceCallingOrSelfPermission(LOCAL_MAC_ADDRESS_PERM, "Need LOCAL_MAC_ADDRESS permission"); 1698 1699 String addrString = null; 1700 byte[] address = mAdapterProperties.getAddress(); 1701 return Utils.getAddressStringFromByte(address); 1702 } 1703 1704 ParcelUuid[] getUuids() { 1705 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1706 1707 return mAdapterProperties.getUuids(); 1708 } 1709 1710 public String getName() { 1711 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1712 1713 try { 1714 return mAdapterProperties.getName(); 1715 } catch (Throwable t) { 1716 debugLog("getName() - Unexpected exception (" + t + ")"); 1717 } 1718 return null; 1719 } 1720 1721 boolean setName(String name) { 1722 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1723 1724 return mAdapterProperties.setName(name); 1725 } 1726 1727 BluetoothClass getBluetoothClass() { 1728 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1729 1730 return mAdapterProperties.getBluetoothClass(); 1731 } 1732 1733 /** 1734 * Sets the Bluetooth CoD on the local adapter and also modifies the storage config for it. 1735 * 1736 * <p>Once set, this value persists across reboots. 1737 */ 1738 boolean setBluetoothClass(BluetoothClass bluetoothClass) { 1739 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1740 "Need BLUETOOTH PRIVILEGED permission"); 1741 debugLog("setBluetoothClass() to " + bluetoothClass); 1742 boolean result = mAdapterProperties.setBluetoothClass(bluetoothClass); 1743 if (!result) { 1744 Log.e(TAG, "setBluetoothClass() to " + bluetoothClass + " failed"); 1745 } 1746 1747 return result && storeBluetoothClassConfig(bluetoothClass.getClassOfDevice()); 1748 } 1749 1750 int getScanMode() { 1751 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1752 1753 return mAdapterProperties.getScanMode(); 1754 } 1755 1756 boolean setScanMode(int mode, int duration) { 1757 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1758 1759 setDiscoverableTimeout(duration); 1760 1761 int newMode = convertScanModeToHal(mode); 1762 return mAdapterProperties.setScanMode(newMode); 1763 } 1764 1765 int getDiscoverableTimeout() { 1766 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1767 1768 return mAdapterProperties.getDiscoverableTimeout(); 1769 } 1770 1771 boolean setDiscoverableTimeout(int timeout) { 1772 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1773 1774 return mAdapterProperties.setDiscoverableTimeout(timeout); 1775 } 1776 1777 boolean startDiscovery() { 1778 debugLog("startDiscovery"); 1779 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1780 1781 return startDiscoveryNative(); 1782 } 1783 1784 boolean cancelDiscovery() { 1785 debugLog("cancelDiscovery"); 1786 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1787 1788 return cancelDiscoveryNative(); 1789 } 1790 1791 boolean isDiscovering() { 1792 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1793 1794 return mAdapterProperties.isDiscovering(); 1795 } 1796 1797 long getDiscoveryEndMillis() { 1798 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1799 1800 return mAdapterProperties.discoveryEndMillis(); 1801 } 1802 1803 public BluetoothDevice[] getBondedDevices() { 1804 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1805 return mAdapterProperties.getBondedDevices(); 1806 } 1807 1808 int getAdapterConnectionState() { 1809 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1810 return mAdapterProperties.getConnectionState(); 1811 } 1812 1813 int getProfileConnectionState(int profile) { 1814 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1815 1816 return mAdapterProperties.getProfileConnectionState(profile); 1817 } 1818 1819 boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { 1820 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1821 if (mSdpManager != null) { 1822 mSdpManager.sdpSearch(device, uuid); 1823 return true; 1824 } else { 1825 return false; 1826 } 1827 } 1828 1829 boolean createBond(BluetoothDevice device, int transport, OobData oobData) { 1830 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1831 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1832 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 1833 return false; 1834 } 1835 1836 mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); 1837 1838 // Pairing is unreliable while scanning, so cancel discovery 1839 // Note, remove this when native stack improves 1840 cancelDiscoveryNative(); 1841 1842 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 1843 msg.obj = device; 1844 msg.arg1 = transport; 1845 1846 if (oobData != null) { 1847 Bundle oobDataBundle = new Bundle(); 1848 oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData); 1849 msg.setData(oobDataBundle); 1850 } 1851 mBondStateMachine.sendMessage(msg); 1852 return true; 1853 } 1854 1855 public boolean isQuietModeEnabled() { 1856 debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode); 1857 return mQuietmode; 1858 } 1859 1860 public void updateUuids() { 1861 debugLog("updateUuids() - Updating UUIDs for bonded devices"); 1862 BluetoothDevice[] bondedDevices = getBondedDevices(); 1863 if (bondedDevices == null) { 1864 return; 1865 } 1866 1867 for (BluetoothDevice device : bondedDevices) { 1868 mRemoteDevices.updateUuids(device); 1869 } 1870 } 1871 1872 boolean cancelBondProcess(BluetoothDevice device) { 1873 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1874 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1875 1876 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1877 if (deviceProp != null) { 1878 deviceProp.setBondingInitiatedLocally(false); 1879 } 1880 1881 return cancelBondNative(addr); 1882 } 1883 1884 boolean removeBond(BluetoothDevice device) { 1885 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1886 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1887 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 1888 return false; 1889 } 1890 deviceProp.setBondingInitiatedLocally(false); 1891 1892 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 1893 msg.obj = device; 1894 mBondStateMachine.sendMessage(msg); 1895 return true; 1896 } 1897 1898 int getBondState(BluetoothDevice device) { 1899 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1900 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1901 if (deviceProp == null) { 1902 return BluetoothDevice.BOND_NONE; 1903 } 1904 return deviceProp.getBondState(); 1905 } 1906 1907 boolean isBondingInitiatedLocally(BluetoothDevice device) { 1908 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1909 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1910 if (deviceProp == null) { 1911 return false; 1912 } 1913 return deviceProp.isBondingInitiatedLocally(); 1914 } 1915 1916 long getSupportedProfiles() { 1917 return Config.getSupportedProfilesBitMask(); 1918 } 1919 1920 int getConnectionState(BluetoothDevice device) { 1921 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1922 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1923 return getConnectionStateNative(addr); 1924 } 1925 1926 String getRemoteName(BluetoothDevice device) { 1927 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1928 if (mRemoteDevices == null) { 1929 return null; 1930 } 1931 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1932 if (deviceProp == null) { 1933 return null; 1934 } 1935 return deviceProp.getName(); 1936 } 1937 1938 int getRemoteType(BluetoothDevice device) { 1939 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1940 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1941 if (deviceProp == null) { 1942 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1943 } 1944 return deviceProp.getDeviceType(); 1945 } 1946 1947 String getRemoteAlias(BluetoothDevice device) { 1948 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1949 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1950 if (deviceProp == null) { 1951 return null; 1952 } 1953 return deviceProp.getAlias(); 1954 } 1955 1956 boolean setRemoteAlias(BluetoothDevice device, String name) { 1957 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1958 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1959 if (deviceProp == null) { 1960 return false; 1961 } 1962 deviceProp.setAlias(device, name); 1963 return true; 1964 } 1965 1966 int getRemoteClass(BluetoothDevice device) { 1967 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1968 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1969 if (deviceProp == null) { 1970 return 0; 1971 } 1972 1973 return deviceProp.getBluetoothClass(); 1974 } 1975 1976 /** 1977 * Get UUIDs for service supported by a remote device 1978 * 1979 * @param device the remote device that we want to get UUIDs from 1980 * @return 1981 */ 1982 @VisibleForTesting 1983 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1984 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1985 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1986 if (deviceProp == null) { 1987 return null; 1988 } 1989 return deviceProp.getUuids(); 1990 } 1991 1992 boolean fetchRemoteUuids(BluetoothDevice device) { 1993 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1994 mRemoteDevices.fetchUuids(device); 1995 return true; 1996 } 1997 1998 int getBatteryLevel(BluetoothDevice device) { 1999 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2000 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2001 if (deviceProp == null) { 2002 return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 2003 } 2004 return deviceProp.getBatteryLevel(); 2005 } 2006 2007 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 2008 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 2009 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2010 // Only allow setting a pin in bonding state, or bonded state in case of security upgrade. 2011 if (deviceProp == null || (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING 2012 && deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) { 2013 return false; 2014 } 2015 2016 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 2017 return pinReplyNative(addr, accept, len, pinCode); 2018 } 2019 2020 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 2021 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2022 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2023 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 2024 return false; 2025 } 2026 2027 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 2028 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 2029 Utils.byteArrayToInt(passkey)); 2030 } 2031 2032 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 2033 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2034 "Need BLUETOOTH PRIVILEGED permission"); 2035 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 2036 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 2037 return false; 2038 } 2039 2040 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 2041 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, accept, 2042 0); 2043 } 2044 2045 int getPhonebookAccessPermission(BluetoothDevice device) { 2046 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2047 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 2048 Context.MODE_PRIVATE); 2049 if (!pref.contains(device.getAddress())) { 2050 return BluetoothDevice.ACCESS_UNKNOWN; 2051 } 2052 return pref.getBoolean(device.getAddress(), false) ? BluetoothDevice.ACCESS_ALLOWED 2053 : BluetoothDevice.ACCESS_REJECTED; 2054 } 2055 2056 boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 2057 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2058 "Need BLUETOOTH PRIVILEGED permission"); 2059 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 2060 Context.MODE_PRIVATE); 2061 SharedPreferences.Editor editor = pref.edit(); 2062 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 2063 editor.remove(device.getAddress()); 2064 } else { 2065 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 2066 } 2067 editor.apply(); 2068 return true; 2069 } 2070 2071 int getMessageAccessPermission(BluetoothDevice device) { 2072 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2073 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 2074 Context.MODE_PRIVATE); 2075 if (!pref.contains(device.getAddress())) { 2076 return BluetoothDevice.ACCESS_UNKNOWN; 2077 } 2078 return pref.getBoolean(device.getAddress(), false) ? BluetoothDevice.ACCESS_ALLOWED 2079 : BluetoothDevice.ACCESS_REJECTED; 2080 } 2081 2082 boolean setMessageAccessPermission(BluetoothDevice device, int value) { 2083 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2084 "Need BLUETOOTH PRIVILEGED permission"); 2085 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 2086 Context.MODE_PRIVATE); 2087 SharedPreferences.Editor editor = pref.edit(); 2088 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 2089 editor.remove(device.getAddress()); 2090 } else { 2091 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 2092 } 2093 editor.apply(); 2094 return true; 2095 } 2096 2097 int getSimAccessPermission(BluetoothDevice device) { 2098 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2099 SharedPreferences pref = 2100 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 2101 if (!pref.contains(device.getAddress())) { 2102 return BluetoothDevice.ACCESS_UNKNOWN; 2103 } 2104 return pref.getBoolean(device.getAddress(), false) ? BluetoothDevice.ACCESS_ALLOWED 2105 : BluetoothDevice.ACCESS_REJECTED; 2106 } 2107 2108 boolean setSimAccessPermission(BluetoothDevice device, int value) { 2109 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2110 "Need BLUETOOTH PRIVILEGED permission"); 2111 SharedPreferences pref = 2112 getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE); 2113 SharedPreferences.Editor editor = pref.edit(); 2114 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 2115 editor.remove(device.getAddress()); 2116 } else { 2117 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 2118 } 2119 editor.apply(); 2120 return true; 2121 } 2122 2123 void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) { 2124 // TODO(BT) permission check? 2125 // Since this is a binder call check if Bluetooth is on still 2126 if (getState() == BluetoothAdapter.STATE_OFF) { 2127 return; 2128 } 2129 2130 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 2131 2132 } 2133 2134 IBluetoothSocketManager getSocketManager() { 2135 android.os.IBinder obj = getSocketManagerNative(); 2136 if (obj == null) { 2137 return null; 2138 } 2139 2140 return IBluetoothSocketManager.Stub.asInterface(obj); 2141 } 2142 2143 boolean factoryReset() { 2144 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2145 return factoryResetNative(); 2146 } 2147 2148 void registerCallback(IBluetoothCallback cb) { 2149 mCallbacks.register(cb); 2150 } 2151 2152 void unregisterCallback(IBluetoothCallback cb) { 2153 mCallbacks.unregister(cb); 2154 } 2155 2156 public int getNumOfAdvertisementInstancesSupported() { 2157 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2158 return mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 2159 } 2160 2161 public boolean isMultiAdvertisementSupported() { 2162 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2163 return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA; 2164 } 2165 2166 public boolean isRpaOffloadSupported() { 2167 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2168 return mAdapterProperties.isRpaOffloadSupported(); 2169 } 2170 2171 public int getNumOfOffloadedIrkSupported() { 2172 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2173 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 2174 } 2175 2176 public int getNumOfOffloadedScanFilterSupported() { 2177 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2178 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 2179 } 2180 2181 public int getOffloadedScanResultStorage() { 2182 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2183 return mAdapterProperties.getOffloadedScanResultStorage(); 2184 } 2185 2186 private boolean isActivityAndEnergyReportingSupported() { 2187 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2188 return mAdapterProperties.isActivityAndEnergyReportingSupported(); 2189 } 2190 2191 public boolean isLe2MPhySupported() { 2192 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2193 return mAdapterProperties.isLe2MPhySupported(); 2194 } 2195 2196 public boolean isLeCodedPhySupported() { 2197 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2198 return mAdapterProperties.isLeCodedPhySupported(); 2199 } 2200 2201 public boolean isLeExtendedAdvertisingSupported() { 2202 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2203 return mAdapterProperties.isLeExtendedAdvertisingSupported(); 2204 } 2205 2206 public boolean isLePeriodicAdvertisingSupported() { 2207 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2208 return mAdapterProperties.isLePeriodicAdvertisingSupported(); 2209 } 2210 2211 public int getLeMaximumAdvertisingDataLength() { 2212 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2213 return mAdapterProperties.getLeMaximumAdvertisingDataLength(); 2214 } 2215 2216 /** 2217 * Get the maximum number of connected audio devices. 2218 * 2219 * @return the maximum number of connected audio devices 2220 */ 2221 public int getMaxConnectedAudioDevices() { 2222 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2223 return mAdapterProperties.getMaxConnectedAudioDevices(); 2224 } 2225 2226 private BluetoothActivityEnergyInfo reportActivityInfo() { 2227 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 2228 if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON 2229 || !mAdapterProperties.isActivityAndEnergyReportingSupported()) { 2230 return null; 2231 } 2232 2233 // Pull the data. The callback will notify mEnergyInfoLock. 2234 readEnergyInfo(); 2235 2236 synchronized (mEnergyInfoLock) { 2237 try { 2238 mEnergyInfoLock.wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); 2239 } catch (InterruptedException e) { 2240 // Just continue, the energy data may be stale but we won't miss anything next time 2241 // we query. 2242 } 2243 2244 final BluetoothActivityEnergyInfo info = 2245 new BluetoothActivityEnergyInfo(SystemClock.elapsedRealtime(), 2246 mStackReportedState, mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs, 2247 mEnergyUsedTotalVoltAmpSecMicro); 2248 2249 // Count the number of entries that have byte counts > 0 2250 int arrayLen = 0; 2251 for (int i = 0; i < mUidTraffic.size(); i++) { 2252 final UidTraffic traffic = mUidTraffic.valueAt(i); 2253 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 2254 arrayLen++; 2255 } 2256 } 2257 2258 // Copy the traffic objects whose byte counts are > 0 and reset the originals. 2259 final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null; 2260 int putIdx = 0; 2261 for (int i = 0; i < mUidTraffic.size(); i++) { 2262 final UidTraffic traffic = mUidTraffic.valueAt(i); 2263 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 2264 result[putIdx++] = traffic.clone(); 2265 traffic.setRxBytes(0); 2266 traffic.setTxBytes(0); 2267 } 2268 } 2269 2270 info.setUidTraffic(result); 2271 2272 // Read on clear values; a record of data is created with 2273 // timstamp and new samples are collected until read again 2274 mStackReportedState = 0; 2275 mTxTimeTotalMs = 0; 2276 mRxTimeTotalMs = 0; 2277 mIdleTimeTotalMs = 0; 2278 mEnergyUsedTotalVoltAmpSecMicro = 0; 2279 return info; 2280 } 2281 } 2282 2283 public int getTotalNumOfTrackableAdvertisements() { 2284 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2285 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 2286 } 2287 2288 public void onLeServiceUp() { 2289 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 2290 mAdapterStateMachine.sendMessage(m); 2291 } 2292 2293 public void onBrEdrDown() { 2294 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 2295 mAdapterStateMachine.sendMessage(m); 2296 } 2297 2298 private static int convertScanModeToHal(int mode) { 2299 switch (mode) { 2300 case BluetoothAdapter.SCAN_MODE_NONE: 2301 return AbstractionLayer.BT_SCAN_MODE_NONE; 2302 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 2303 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 2304 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 2305 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2306 } 2307 // errorLog("Incorrect scan mode in convertScanModeToHal"); 2308 return -1; 2309 } 2310 2311 static int convertScanModeFromHal(int mode) { 2312 switch (mode) { 2313 case AbstractionLayer.BT_SCAN_MODE_NONE: 2314 return BluetoothAdapter.SCAN_MODE_NONE; 2315 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 2316 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 2317 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 2318 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2319 } 2320 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 2321 return -1; 2322 } 2323 2324 // This function is called from JNI. It allows native code to set a single wake 2325 // alarm. If an alarm is already pending and a new request comes in, the alarm 2326 // will be rescheduled (i.e. the previously set alarm will be cancelled). 2327 private boolean setWakeAlarm(long delayMillis, boolean shouldWake) { 2328 synchronized (this) { 2329 if (mPendingAlarm != null) { 2330 mAlarmManager.cancel(mPendingAlarm); 2331 } 2332 2333 long wakeupTime = SystemClock.elapsedRealtime() + delayMillis; 2334 int type = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP 2335 : AlarmManager.ELAPSED_REALTIME; 2336 2337 Intent intent = new Intent(ACTION_ALARM_WAKEUP); 2338 mPendingAlarm = 2339 PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); 2340 mAlarmManager.setExact(type, wakeupTime, mPendingAlarm); 2341 return true; 2342 } 2343 } 2344 2345 // This function is called from JNI. It allows native code to acquire a single wake lock. 2346 // If the wake lock is already held, this function returns success. Although this function 2347 // only supports acquiring a single wake lock at a time right now, it will eventually be 2348 // extended to allow acquiring an arbitrary number of wake locks. The current interface 2349 // takes |lockName| as a parameter in anticipation of that implementation. 2350 private boolean acquireWakeLock(String lockName) { 2351 synchronized (this) { 2352 if (mWakeLock == null) { 2353 mWakeLockName = lockName; 2354 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 2355 } 2356 2357 if (!mWakeLock.isHeld()) { 2358 mWakeLock.acquire(); 2359 } 2360 } 2361 return true; 2362 } 2363 2364 // This function is called from JNI. It allows native code to release a wake lock acquired 2365 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 2366 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 2367 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. 2368 private boolean releaseWakeLock(String lockName) { 2369 synchronized (this) { 2370 if (mWakeLock == null) { 2371 errorLog("Repeated wake lock release; aborting release: " + lockName); 2372 return false; 2373 } 2374 2375 if (mWakeLock.isHeld()) { 2376 mWakeLock.release(); 2377 } 2378 } 2379 return true; 2380 } 2381 2382 private void energyInfoCallback(int status, int ctrlState, long txTime, long rxTime, 2383 long idleTime, long energyUsed, UidTraffic[] data) throws RemoteException { 2384 if (ctrlState >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID 2385 && ctrlState <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 2386 // Energy is product of mA, V and ms. If the chipset doesn't 2387 // report it, we have to compute it from time 2388 if (energyUsed == 0) { 2389 try { 2390 final long txMah = Math.multiplyExact(txTime, getTxCurrentMa()); 2391 final long rxMah = Math.multiplyExact(rxTime, getRxCurrentMa()); 2392 final long idleMah = Math.multiplyExact(idleTime, getIdleCurrentMa()); 2393 energyUsed = (long) (Math.addExact(Math.addExact(txMah, rxMah), idleMah) 2394 * getOperatingVolt()); 2395 } catch (ArithmeticException e) { 2396 Slog.wtf(TAG, "overflow in bluetooth energy callback", e); 2397 // Energy is already 0 if the exception was thrown. 2398 } 2399 } 2400 2401 synchronized (mEnergyInfoLock) { 2402 mStackReportedState = ctrlState; 2403 long totalTxTimeMs; 2404 long totalRxTimeMs; 2405 long totalIdleTimeMs; 2406 long totalEnergy; 2407 try { 2408 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, txTime); 2409 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rxTime); 2410 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idleTime); 2411 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energyUsed); 2412 } catch (ArithmeticException e) { 2413 // This could be because we accumulated a lot of time, or we got a very strange 2414 // value from the controller (more likely). Discard this data. 2415 Slog.wtf(TAG, "overflow in bluetooth energy callback", e); 2416 totalTxTimeMs = mTxTimeTotalMs; 2417 totalRxTimeMs = mRxTimeTotalMs; 2418 totalIdleTimeMs = mIdleTimeTotalMs; 2419 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro; 2420 } 2421 2422 mTxTimeTotalMs = totalTxTimeMs; 2423 mRxTimeTotalMs = totalRxTimeMs; 2424 mIdleTimeTotalMs = totalIdleTimeMs; 2425 mEnergyUsedTotalVoltAmpSecMicro = totalEnergy; 2426 2427 for (UidTraffic traffic : data) { 2428 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid()); 2429 if (existingTraffic == null) { 2430 mUidTraffic.put(traffic.getUid(), traffic); 2431 } else { 2432 existingTraffic.addRxBytes(traffic.getRxBytes()); 2433 existingTraffic.addTxBytes(traffic.getTxBytes()); 2434 } 2435 } 2436 mEnergyInfoLock.notifyAll(); 2437 } 2438 } 2439 2440 verboseLog("energyInfoCallback() status = " + status + "txTime = " + txTime + "rxTime = " 2441 + rxTime + "idleTime = " + idleTime + "energyUsed = " + energyUsed + "ctrlState = " 2442 + ctrlState + "traffic = " + Arrays.toString(data)); 2443 } 2444 2445 private int getIdleCurrentMa() { 2446 return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma); 2447 } 2448 2449 private int getTxCurrentMa() { 2450 return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma); 2451 } 2452 2453 private int getRxCurrentMa() { 2454 return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma); 2455 } 2456 2457 private double getOperatingVolt() { 2458 return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0; 2459 } 2460 2461 @Override 2462 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 2463 enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 2464 2465 if (args.length == 0) { 2466 writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section."); 2467 writer.println("Use --print argument for dumpsys direct from AdapterService."); 2468 return; 2469 } 2470 2471 verboseLog("dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args)); 2472 if (args[0].startsWith("--proto")) { 2473 if (args[0].equals("--proto-java-bin")) { 2474 dumpJava(fd); 2475 } else { 2476 dumpNative(fd, args); 2477 } 2478 return; 2479 } 2480 2481 writer.println("Bonded devices:"); 2482 for (BluetoothDevice device : getBondedDevices()) { 2483 writer.println( 2484 " " + device.getAddress() + " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " 2485 + device.getName()); 2486 } 2487 2488 // Dump profile information 2489 StringBuilder sb = new StringBuilder(); 2490 synchronized (mProfiles) { 2491 for (ProfileService profile : mProfiles) { 2492 profile.dump(sb); 2493 } 2494 } 2495 2496 writer.write(sb.toString()); 2497 writer.flush(); 2498 2499 dumpNative(fd, args); 2500 } 2501 2502 private void dumpJava(FileDescriptor fd) { 2503 BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog(); 2504 log.setNumBondedDevices(getBondedDevices().length); 2505 2506 for (ProfileService profile : mProfiles) { 2507 profile.dumpProto(log); 2508 } 2509 2510 try { 2511 FileOutputStream protoOut = new FileOutputStream(fd); 2512 String protoOutString = Base64.encodeToString(log.toByteArray(), Base64.DEFAULT); 2513 protoOut.write(protoOutString.getBytes(StandardCharsets.UTF_8)); 2514 protoOut.close(); 2515 } catch (IOException e) { 2516 errorLog("Unable to write Java protobuf to file descriptor."); 2517 } 2518 } 2519 2520 private void debugLog(String msg) { 2521 if (DBG) { 2522 Log.d(TAG, msg); 2523 } 2524 } 2525 2526 private void verboseLog(String msg) { 2527 if (VERBOSE) { 2528 Log.v(TAG, msg); 2529 } 2530 } 2531 2532 private void errorLog(String msg) { 2533 Log.e(TAG, msg); 2534 } 2535 2536 private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() { 2537 @Override 2538 public void onReceive(Context context, Intent intent) { 2539 synchronized (AdapterService.this) { 2540 mPendingAlarm = null; 2541 alarmFiredNative(); 2542 } 2543 } 2544 }; 2545 2546 private static native void classInitNative(); 2547 2548 private native boolean initNative(); 2549 2550 private native void cleanupNative(); 2551 2552 /*package*/ 2553 native boolean enableNative(boolean startRestricted); 2554 2555 /*package*/ 2556 native boolean disableNative(); 2557 2558 /*package*/ 2559 native boolean setAdapterPropertyNative(int type, byte[] val); 2560 2561 /*package*/ 2562 native boolean getAdapterPropertiesNative(); 2563 2564 /*package*/ 2565 native boolean getAdapterPropertyNative(int type); 2566 2567 /*package*/ 2568 native boolean setAdapterPropertyNative(int type); 2569 2570 /*package*/ 2571 native boolean setDevicePropertyNative(byte[] address, int type, byte[] val); 2572 2573 /*package*/ 2574 native boolean getDevicePropertyNative(byte[] address, int type); 2575 2576 /*package*/ 2577 native boolean createBondNative(byte[] address, int transport); 2578 2579 /*package*/ 2580 native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData); 2581 2582 /*package*/ 2583 native boolean removeBondNative(byte[] address); 2584 2585 /*package*/ 2586 native boolean cancelBondNative(byte[] address); 2587 2588 /*package*/ 2589 native boolean sdpSearchNative(byte[] address, byte[] uuid); 2590 2591 /*package*/ 2592 native int getConnectionStateNative(byte[] address); 2593 2594 private native boolean startDiscoveryNative(); 2595 2596 private native boolean cancelDiscoveryNative(); 2597 2598 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 2599 2600 private native boolean sspReplyNative(byte[] address, int type, boolean accept, int passkey); 2601 2602 /*package*/ 2603 native boolean getRemoteServicesNative(byte[] address); 2604 2605 /*package*/ 2606 native boolean getRemoteMasInstancesNative(byte[] address); 2607 2608 private native int readEnergyInfo(); 2609 2610 private native IBinder getSocketManagerNative(); 2611 2612 private native void setSystemUiUidNative(int systemUiUid); 2613 2614 private static native void setForegroundUserIdNative(int foregroundUserId); 2615 2616 /*package*/ 2617 native boolean factoryResetNative(); 2618 2619 private native void alarmFiredNative(); 2620 2621 private native void dumpNative(FileDescriptor fd, String[] arguments); 2622 2623 private native void interopDatabaseClearNative(); 2624 2625 private native void interopDatabaseAddNative(int feature, byte[] address, int length); 2626 2627 // Returns if this is a mock object. This is currently used in testing so that we may not call 2628 // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up 2629 // calling finalize() which in turn calls System.exit() and the process crashes. 2630 // 2631 // Mock this in your testing framework to return true to avoid the mentioned behavior. In 2632 // production this has no effect. 2633 public boolean isMock() { 2634 return false; 2635 } 2636} 2637