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