AdapterService.java revision 90d55ae85dc19e33fffe1e51787df2b8dd40c230
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 if (!isMock()) { 468 // TODO(b/27859763) 469 Log.i(TAG, "Force exit to cleanup internal state in Bluetooth stack"); 470 System.exit(0); 471 } 472 } 473 474 void BleOnProcessStart() { 475 debugLog("BleOnProcessStart()"); 476 477 if (getResources().getBoolean( 478 R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) { 479 Config.init(getApplicationContext()); 480 } 481 482 Class[] supportedProfileServices = Config.getSupportedProfiles(); 483 //Initialize data objects 484 for (int i=0; i < supportedProfileServices.length;i++) { 485 mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); 486 } 487 488 // Reset |mRemoteDevices| whenever BLE is turned off then on 489 // This is to replace the fact that |mRemoteDevices| was 490 // reinitialized in previous code. 491 // 492 // TODO(apanicke): The reason is unclear but 493 // I believe it is to clear the variable every time BLE was 494 // turned off then on. The same effect can be achieved by 495 // calling cleanup but this may not be necessary at all 496 // We should figure out why this is needed later 497 mRemoteDevices.cleanup(); 498 mAdapterProperties.init(mRemoteDevices); 499 500 debugLog("BleOnProcessStart() - Make Bond State Machine"); 501 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 502 503 mJniCallbacks.init(mBondStateMachine,mRemoteDevices); 504 505 try { 506 mBatteryStats.noteResetBleScan(); 507 } catch (RemoteException e) { 508 // Ignore. 509 } 510 511 //Start Gatt service 512 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 513 } 514 515 void startCoreServices() 516 { 517 debugLog("startCoreServices()"); 518 Class[] supportedProfileServices = Config.getSupportedProfiles(); 519 520 //Start profile services 521 if (!mProfilesStarted && supportedProfileServices.length >0) { 522 //Startup all profile services 523 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 524 }else { 525 debugLog("startCoreProfiles(): Profile Services alreay started"); 526 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BREDR_STARTED)); 527 } 528 } 529 530 void startBluetoothDisable() { 531 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE)); 532 } 533 534 boolean stopProfileServices() { 535 Class[] supportedProfileServices = Config.getSupportedProfiles(); 536 if (mProfilesStarted && supportedProfileServices.length>0) { 537 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 538 return true; 539 } 540 debugLog("stopProfileServices() - No profiles services to stop or already stopped."); 541 return false; 542 } 543 544 boolean stopGattProfileService() { 545 //TODO: can optimize this instead of looping around all supported profiles 546 debugLog("stopGattProfileService()"); 547 Class[] supportedProfileServices = Config.getSupportedProfiles(); 548 549 setGattProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 550 return true; 551 } 552 553 554 void updateAdapterState(int prevState, int newState){ 555 if (mCallbacks !=null) { 556 int n=mCallbacks.beginBroadcast(); 557 debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 558 for (int i=0; i <n;i++) { 559 try { 560 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); 561 } catch (RemoteException e) { 562 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 563 } 564 } 565 mCallbacks.finishBroadcast(); 566 } 567 } 568 569 void cleanup () { 570 debugLog("cleanup()"); 571 if (mCleaningUp) { 572 errorLog("cleanup() - Service already starting to cleanup, ignoring request..."); 573 return; 574 } 575 576 mCleaningUp = true; 577 578 unregisterReceiver(mAlarmBroadcastReceiver); 579 580 if (mPendingAlarm != null) { 581 mAlarmManager.cancel(mPendingAlarm); 582 mPendingAlarm = null; 583 } 584 585 // This wake lock release may also be called concurrently by 586 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 587 synchronized (this) { 588 if (mWakeLock != null) { 589 if (mWakeLock.isHeld()) 590 mWakeLock.release(); 591 mWakeLock = null; 592 } 593 } 594 595 if (mAdapterStateMachine != null) { 596 mAdapterStateMachine.doQuit(); 597 mAdapterStateMachine.cleanup(); 598 } 599 600 if (mBondStateMachine != null) { 601 mBondStateMachine.doQuit(); 602 mBondStateMachine.cleanup(); 603 } 604 605 if (mRemoteDevices != null) { 606 mRemoteDevices.cleanup(); 607 } 608 609 if(mSdpManager != null) { 610 mSdpManager.cleanup(); 611 mSdpManager = null; 612 } 613 614 if (mNativeAvailable) { 615 debugLog("cleanup() - Cleaning up adapter native"); 616 cleanupNative(); 617 mNativeAvailable=false; 618 } 619 620 if (mAdapterProperties != null) { 621 mAdapterProperties.cleanup(); 622 } 623 624 if (mJniCallbacks != null) { 625 mJniCallbacks.cleanup(); 626 } 627 628 if (mPhonePolicy != null) { 629 mPhonePolicy.cleanup(); 630 } 631 632 if (mProfileServicesState != null) { 633 mProfileServicesState.clear(); 634 } 635 636 clearAdapterService(); 637 638 if (mBinder != null) { 639 mBinder.cleanup(); 640 mBinder = null; //Do not remove. Otherwise Binder leak! 641 } 642 643 if (mCallbacks !=null) { 644 mCallbacks.kill(); 645 } 646 } 647 648 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 649 650 private final Handler mHandler = new Handler() { 651 @Override 652 public void handleMessage(Message msg) { 653 debugLog("handleMessage() - Message: " + msg.what); 654 655 switch (msg.what) { 656 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 657 debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 658 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 659 } 660 break; 661 } 662 } 663 }; 664 665 @SuppressWarnings("rawtypes") 666 private void setGattProfileServiceState(Class[] services, int state) { 667 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 668 Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving..."); 669 return; 670 } 671 672 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 673 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 674 675 if (state == BluetoothAdapter.STATE_OFF) { 676 expectedCurrentState= BluetoothAdapter.STATE_ON; 677 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 678 } 679 680 for (int i=0; i <services.length;i++) { 681 String serviceName = services[i].getName(); 682 String simpleName = services[i].getSimpleName(); 683 684 if (simpleName.equals("GattService")) { 685 Integer serviceState = mProfileServicesState.get(serviceName); 686 687 if(serviceState != null && serviceState != expectedCurrentState) { 688 debugLog("setProfileServiceState() - Unable to " 689 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 690 + " service " + serviceName 691 + ". Invalid state: " + serviceState); 692 continue; 693 } 694 debugLog("setProfileServiceState() - " 695 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 696 + " service " + serviceName); 697 698 mProfileServicesState.put(serviceName,pendingState); 699 Intent intent = new Intent(this,services[i]); 700 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 701 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 702 startService(intent); 703 return; 704 } 705 } 706 } 707 708 709 @SuppressWarnings("rawtypes") 710 private void setProfileServiceState(Class[] services, int state) { 711 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 712 debugLog("setProfileServiceState() - Invalid state, leaving..."); 713 return; 714 } 715 716 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 717 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 718 if (state == BluetoothAdapter.STATE_OFF) { 719 expectedCurrentState= BluetoothAdapter.STATE_ON; 720 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 721 } 722 723 for (int i=0; i <services.length;i++) { 724 String serviceName = services[i].getName(); 725 String simpleName = services[i].getSimpleName(); 726 727 if (simpleName.equals("GattService")) continue; 728 729 Integer serviceState = mProfileServicesState.get(serviceName); 730 if(serviceState != null && serviceState != expectedCurrentState) { 731 debugLog("setProfileServiceState() - Unable to " 732 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 733 + " service " + serviceName 734 + ". Invalid state: " + serviceState); 735 continue; 736 } 737 738 debugLog("setProfileServiceState() - " 739 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 740 + " service " + serviceName); 741 742 mProfileServicesState.put(serviceName,pendingState); 743 Intent intent = new Intent(this,services[i]); 744 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 745 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 746 startService(intent); 747 } 748 } 749 750 private boolean isAvailable() { 751 return !mCleaningUp; 752 } 753 754 /** 755 * Handlers for incoming service calls 756 */ 757 private AdapterServiceBinder mBinder; 758 759 /** 760 * The Binder implementation must be declared to be a static class, with 761 * the AdapterService instance passed in the constructor. Furthermore, 762 * when the AdapterService shuts down, the reference to the AdapterService 763 * must be explicitly removed. 764 * 765 * Otherwise, a memory leak can occur from repeated starting/stopping the 766 * service...Please refer to android.os.Binder for further details on 767 * why an inner instance class should be avoided. 768 * 769 */ 770 private static class AdapterServiceBinder extends IBluetooth.Stub { 771 private AdapterService mService; 772 773 public AdapterServiceBinder(AdapterService svc) { 774 mService = svc; 775 } 776 public boolean cleanup() { 777 mService = null; 778 return true; 779 } 780 781 public AdapterService getService() { 782 if (mService != null && mService.isAvailable()) { 783 return mService; 784 } 785 return null; 786 } 787 public boolean isEnabled() { 788 // don't check caller, may be called from system UI 789 AdapterService service = getService(); 790 if (service == null) return false; 791 return service.isEnabled(); 792 } 793 794 public int getState() { 795 // don't check caller, may be called from system UI 796 AdapterService service = getService(); 797 if (service == null) return BluetoothAdapter.STATE_OFF; 798 return service.getState(); 799 } 800 801 public boolean enable() { 802 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 803 (!Utils.checkCaller())) { 804 Log.w(TAG, "enable() - Not allowed for non-active user and non system user"); 805 return false; 806 } 807 AdapterService service = getService(); 808 if (service == null) return false; 809 return service.enable(); 810 } 811 812 public boolean enableNoAutoConnect() { 813 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 814 (!Utils.checkCaller())) { 815 Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user"); 816 return false; 817 } 818 819 AdapterService service = getService(); 820 if (service == null) return false; 821 return service.enableNoAutoConnect(); 822 } 823 824 public boolean disable() { 825 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 826 (!Utils.checkCaller())) { 827 Log.w(TAG, "disable() - Not allowed for non-active user and non system user"); 828 return false; 829 } 830 831 AdapterService service = getService(); 832 if (service == null) return false; 833 return service.disable(); 834 } 835 836 public String getAddress() { 837 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 838 (!Utils.checkCallerAllowManagedProfiles(mService))) { 839 Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user"); 840 return null; 841 } 842 843 AdapterService service = getService(); 844 if (service == null) return null; 845 return service.getAddress(); 846 } 847 848 public ParcelUuid[] getUuids() { 849 if (!Utils.checkCaller()) { 850 Log.w(TAG, "getUuids() - Not allowed for non-active user"); 851 return new ParcelUuid[0]; 852 } 853 854 AdapterService service = getService(); 855 if (service == null) return new ParcelUuid[0]; 856 return service.getUuids(); 857 } 858 859 public String getName() { 860 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 861 (!Utils.checkCaller())) { 862 Log.w(TAG, "getName() - Not allowed for non-active user and non system user"); 863 return null; 864 } 865 866 AdapterService service = getService(); 867 if (service == null) return null; 868 return service.getName(); 869 } 870 871 public boolean setName(String name) { 872 if (!Utils.checkCaller()) { 873 Log.w(TAG, "setName() - Not allowed for non-active user"); 874 return false; 875 } 876 877 AdapterService service = getService(); 878 if (service == null) return false; 879 return service.setName(name); 880 } 881 882 public int getScanMode() { 883 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 884 Log.w(TAG, "getScanMode() - Not allowed for non-active user"); 885 return BluetoothAdapter.SCAN_MODE_NONE; 886 } 887 888 AdapterService service = getService(); 889 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 890 return service.getScanMode(); 891 } 892 893 public boolean setScanMode(int mode, int duration) { 894 if (!Utils.checkCaller()) { 895 Log.w(TAG, "setScanMode() - Not allowed for non-active user"); 896 return false; 897 } 898 899 AdapterService service = getService(); 900 if (service == null) return false; 901 return service.setScanMode(mode,duration); 902 } 903 904 public int getDiscoverableTimeout() { 905 if (!Utils.checkCaller()) { 906 Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user"); 907 return 0; 908 } 909 910 AdapterService service = getService(); 911 if (service == null) return 0; 912 return service.getDiscoverableTimeout(); 913 } 914 915 public boolean setDiscoverableTimeout(int timeout) { 916 if (!Utils.checkCaller()) { 917 Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user"); 918 return false; 919 } 920 921 AdapterService service = getService(); 922 if (service == null) return false; 923 return service.setDiscoverableTimeout(timeout); 924 } 925 926 public boolean startDiscovery() { 927 if (!Utils.checkCaller()) { 928 Log.w(TAG, "startDiscovery() - Not allowed for non-active user"); 929 return false; 930 } 931 932 AdapterService service = getService(); 933 if (service == null) return false; 934 return service.startDiscovery(); 935 } 936 937 public boolean cancelDiscovery() { 938 if (!Utils.checkCaller()) { 939 Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user"); 940 return false; 941 } 942 943 AdapterService service = getService(); 944 if (service == null) return false; 945 return service.cancelDiscovery(); 946 } 947 948 public boolean isDiscovering() { 949 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 950 Log.w(TAG, "isDiscovering() - Not allowed for non-active user"); 951 return false; 952 } 953 954 AdapterService service = getService(); 955 if (service == null) return false; 956 return service.isDiscovering(); 957 } 958 959 public long getDiscoveryEndMillis() { 960 if (!Utils.checkCaller()) { 961 Log.w(TAG, "getDiscoveryEndMillis() - Not allowed for non-active user"); 962 return -1; 963 } 964 965 AdapterService service = getService(); 966 if (service == null) return -1; 967 return service.getDiscoveryEndMillis(); 968 } 969 970 public BluetoothDevice[] getBondedDevices() { 971 // don't check caller, may be called from system UI 972 AdapterService service = getService(); 973 if (service == null) return new BluetoothDevice[0]; 974 return service.getBondedDevices(); 975 } 976 977 public int getAdapterConnectionState() { 978 // don't check caller, may be called from system UI 979 AdapterService service = getService(); 980 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 981 return service.getAdapterConnectionState(); 982 } 983 984 public int getProfileConnectionState(int profile) { 985 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 986 Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user"); 987 return BluetoothProfile.STATE_DISCONNECTED; 988 } 989 990 AdapterService service = getService(); 991 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 992 return service.getProfileConnectionState(profile); 993 } 994 995 public boolean createBond(BluetoothDevice device, int transport) { 996 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 997 Log.w(TAG, "createBond() - Not allowed for non-active user"); 998 return false; 999 } 1000 1001 AdapterService service = getService(); 1002 if (service == null) return false; 1003 return service.createBond(device, transport, null); 1004 } 1005 1006 public boolean createBondOutOfBand(BluetoothDevice device, int transport, OobData oobData) { 1007 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1008 Log.w(TAG, "createBondOutOfBand() - Not allowed for non-active user"); 1009 return false; 1010 } 1011 1012 AdapterService service = getService(); 1013 if (service == null) return false; 1014 return service.createBond(device, transport, oobData); 1015 } 1016 1017 public boolean cancelBondProcess(BluetoothDevice device) { 1018 if (!Utils.checkCaller()) { 1019 Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user"); 1020 return false; 1021 } 1022 1023 AdapterService service = getService(); 1024 if (service == null) return false; 1025 return service.cancelBondProcess(device); 1026 } 1027 1028 public boolean removeBond(BluetoothDevice device) { 1029 if (!Utils.checkCaller()) { 1030 Log.w(TAG, "removeBond() - Not allowed for non-active user"); 1031 return false; 1032 } 1033 1034 AdapterService service = getService(); 1035 if (service == null) return false; 1036 return service.removeBond(device); 1037 } 1038 1039 public int getBondState(BluetoothDevice device) { 1040 // don't check caller, may be called from system UI 1041 AdapterService service = getService(); 1042 if (service == null) return BluetoothDevice.BOND_NONE; 1043 return service.getBondState(device); 1044 } 1045 1046 public boolean isBondingInitiatedLocally(BluetoothDevice device) { 1047 // don't check caller, may be called from system UI 1048 AdapterService service = getService(); 1049 if (service == null) return false; 1050 return service.isBondingInitiatedLocally(device); 1051 } 1052 1053 public long getSupportedProfiles() { 1054 AdapterService service = getService(); 1055 if (service == null) return 0; 1056 return service.getSupportedProfiles(); 1057 } 1058 1059 public int getConnectionState(BluetoothDevice device) { 1060 AdapterService service = getService(); 1061 if (service == null) return 0; 1062 return service.getConnectionState(device); 1063 } 1064 1065 public String getRemoteName(BluetoothDevice device) { 1066 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1067 Log.w(TAG, "getRemoteName() - Not allowed for non-active user"); 1068 return null; 1069 } 1070 1071 AdapterService service = getService(); 1072 if (service == null) return null; 1073 return service.getRemoteName(device); 1074 } 1075 1076 public int getRemoteType(BluetoothDevice device) { 1077 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1078 Log.w(TAG, "getRemoteType() - Not allowed for non-active user"); 1079 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1080 } 1081 1082 AdapterService service = getService(); 1083 if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1084 return service.getRemoteType(device); 1085 } 1086 1087 public String getRemoteAlias(BluetoothDevice device) { 1088 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1089 Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user"); 1090 return null; 1091 } 1092 1093 AdapterService service = getService(); 1094 if (service == null) return null; 1095 return service.getRemoteAlias(device); 1096 } 1097 1098 public boolean setRemoteAlias(BluetoothDevice device, String name) { 1099 if (!Utils.checkCaller()) { 1100 Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user"); 1101 return false; 1102 } 1103 1104 AdapterService service = getService(); 1105 if (service == null) return false; 1106 return service.setRemoteAlias(device, name); 1107 } 1108 1109 public int getRemoteClass(BluetoothDevice device) { 1110 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1111 Log.w(TAG, "getRemoteClass() - Not allowed for non-active user"); 1112 return 0; 1113 } 1114 1115 AdapterService service = getService(); 1116 if (service == null) return 0; 1117 return service.getRemoteClass(device); 1118 } 1119 1120 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1121 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1122 Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user"); 1123 return new ParcelUuid[0]; 1124 } 1125 1126 AdapterService service = getService(); 1127 if (service == null) return new ParcelUuid[0]; 1128 return service.getRemoteUuids(device); 1129 } 1130 1131 public boolean fetchRemoteUuids(BluetoothDevice device) { 1132 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1133 Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user"); 1134 return false; 1135 } 1136 1137 AdapterService service = getService(); 1138 if (service == null) return false; 1139 return service.fetchRemoteUuids(device); 1140 } 1141 1142 1143 1144 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1145 if (!Utils.checkCaller()) { 1146 Log.w(TAG, "setPin() - Not allowed for non-active user"); 1147 return false; 1148 } 1149 1150 AdapterService service = getService(); 1151 if (service == null) return false; 1152 return service.setPin(device, accept, len, pinCode); 1153 } 1154 1155 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1156 if (!Utils.checkCaller()) { 1157 Log.w(TAG, "setPasskey() - Not allowed for non-active user"); 1158 return false; 1159 } 1160 1161 AdapterService service = getService(); 1162 if (service == null) return false; 1163 return service.setPasskey(device, accept, len, passkey); 1164 } 1165 1166 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1167 if (!Utils.checkCaller()) { 1168 Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user"); 1169 return false; 1170 } 1171 1172 AdapterService service = getService(); 1173 if (service == null) return false; 1174 return service.setPairingConfirmation(device, accept); 1175 } 1176 1177 public int getPhonebookAccessPermission(BluetoothDevice device) { 1178 if (!Utils.checkCaller()) { 1179 Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user"); 1180 return BluetoothDevice.ACCESS_UNKNOWN; 1181 } 1182 1183 AdapterService service = getService(); 1184 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1185 return service.getPhonebookAccessPermission(device); 1186 } 1187 1188 public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1189 if (!Utils.checkCaller()) { 1190 Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user"); 1191 return false; 1192 } 1193 1194 AdapterService service = getService(); 1195 if (service == null) return false; 1196 return service.setPhonebookAccessPermission(device, value); 1197 } 1198 1199 public int getMessageAccessPermission(BluetoothDevice device) { 1200 if (!Utils.checkCaller()) { 1201 Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user"); 1202 return BluetoothDevice.ACCESS_UNKNOWN; 1203 } 1204 1205 AdapterService service = getService(); 1206 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1207 return service.getMessageAccessPermission(device); 1208 } 1209 1210 public boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1211 if (!Utils.checkCaller()) { 1212 Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user"); 1213 return false; 1214 } 1215 1216 AdapterService service = getService(); 1217 if (service == null) return false; 1218 return service.setMessageAccessPermission(device, value); 1219 } 1220 1221 public int getSimAccessPermission(BluetoothDevice device) { 1222 if (!Utils.checkCaller()) { 1223 Log.w(TAG, "getSimAccessPermission() - Not allowed for non-active user"); 1224 return BluetoothDevice.ACCESS_UNKNOWN; 1225 } 1226 1227 AdapterService service = getService(); 1228 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1229 return service.getSimAccessPermission(device); 1230 } 1231 1232 public boolean setSimAccessPermission(BluetoothDevice device, int value) { 1233 if (!Utils.checkCaller()) { 1234 Log.w(TAG, "setSimAccessPermission() - Not allowed for non-active user"); 1235 return false; 1236 } 1237 1238 AdapterService service = getService(); 1239 if (service == null) return false; 1240 return service.setSimAccessPermission(device, value); 1241 } 1242 1243 public void sendConnectionStateChange(BluetoothDevice 1244 device, int profile, int state, int prevState) { 1245 AdapterService service = getService(); 1246 if (service == null) return; 1247 service.sendConnectionStateChange(device, profile, state, prevState); 1248 } 1249 1250 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1251 ParcelUuid uuid, int port, int flag) { 1252 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1253 Log.w(TAG, "connectSocket() - Not allowed for non-active user"); 1254 return null; 1255 } 1256 1257 AdapterService service = getService(); 1258 if (service == null) return null; 1259 return service.connectSocket(device, type, uuid, port, flag); 1260 } 1261 1262 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1263 ParcelUuid uuid, int port, int flag) { 1264 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1265 Log.w(TAG, "createSocketChannel() - Not allowed for non-active user"); 1266 return null; 1267 } 1268 1269 AdapterService service = getService(); 1270 if (service == null) return null; 1271 return service.createSocketChannel(type, serviceName, uuid, port, flag); 1272 } 1273 public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid) { 1274 if (!Utils.checkCaller()) { 1275 Log.w(TAG,"sdpSea(): not allowed for non-active user"); 1276 return false; 1277 } 1278 1279 AdapterService service = getService(); 1280 if (service == null) return false; 1281 return service.sdpSearch(device,uuid); 1282 } 1283 1284 public boolean factoryReset() { 1285 AdapterService service = getService(); 1286 if (service == null) return false; 1287 service.disable(); 1288 return service.factoryReset(); 1289 1290 } 1291 1292 public void registerCallback(IBluetoothCallback cb) { 1293 AdapterService service = getService(); 1294 if (service == null) return ; 1295 service.registerCallback(cb); 1296 } 1297 1298 public void unregisterCallback(IBluetoothCallback cb) { 1299 AdapterService service = getService(); 1300 if (service == null) return ; 1301 service.unregisterCallback(cb); 1302 } 1303 1304 public boolean isMultiAdvertisementSupported() { 1305 AdapterService service = getService(); 1306 if (service == null) return false; 1307 return service.isMultiAdvertisementSupported(); 1308 } 1309 1310 public boolean isOffloadedFilteringSupported() { 1311 AdapterService service = getService(); 1312 if (service == null) return false; 1313 int val = service.getNumOfOffloadedScanFilterSupported(); 1314 return (val >= MIN_OFFLOADED_FILTERS); 1315 } 1316 1317 public boolean isOffloadedScanBatchingSupported() { 1318 AdapterService service = getService(); 1319 if (service == null) return false; 1320 int val = service.getOffloadedScanResultStorage(); 1321 return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES); 1322 } 1323 1324 public boolean isLe2MPhySupported() { 1325 AdapterService service = getService(); 1326 if (service == null) return false; 1327 return service.isLe2MPhySupported(); 1328 } 1329 1330 public boolean isLeCodedPhySupported() { 1331 AdapterService service = getService(); 1332 if (service == null) return false; 1333 return service.isLeCodedPhySupported(); 1334 } 1335 1336 public boolean isLeExtendedAdvertisingSupported() { 1337 AdapterService service = getService(); 1338 if (service == null) return false; 1339 return service.isLeExtendedAdvertisingSupported(); 1340 } 1341 1342 public boolean isLePeriodicAdvertisingSupported() { 1343 AdapterService service = getService(); 1344 if (service == null) return false; 1345 return service.isLePeriodicAdvertisingSupported(); 1346 } 1347 1348 public int getLeMaximumAdvertisingDataLength() { 1349 AdapterService service = getService(); 1350 if (service == null) return 0; 1351 return service.getLeMaximumAdvertisingDataLength(); 1352 } 1353 1354 public boolean isActivityAndEnergyReportingSupported() { 1355 AdapterService service = getService(); 1356 if (service == null) return false; 1357 return service.isActivityAndEnergyReportingSupported(); 1358 } 1359 1360 public BluetoothActivityEnergyInfo reportActivityInfo() { 1361 AdapterService service = getService(); 1362 if (service == null) return null; 1363 return service.reportActivityInfo(); 1364 } 1365 1366 public void requestActivityInfo(ResultReceiver result) { 1367 Bundle bundle = new Bundle(); 1368 bundle.putParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY, 1369 reportActivityInfo()); 1370 result.send(0, bundle); 1371 } 1372 1373 public void onLeServiceUp(){ 1374 AdapterService service = getService(); 1375 if (service == null) return; 1376 service.onLeServiceUp(); 1377 } 1378 1379 public void onBrEdrDown(){ 1380 AdapterService service = getService(); 1381 if (service == null) return; 1382 service.onBrEdrDown(); 1383 } 1384 1385 public void dump(FileDescriptor fd, String[] args) { 1386 PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); 1387 AdapterService service = getService(); 1388 if (service == null) return; 1389 service.dump(fd, writer, args); 1390 } 1391 }; 1392 1393 // ----API Methods-------- 1394 1395 public boolean isEnabled() { 1396 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1397 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 1398 } 1399 1400 public int getState() { 1401 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1402 if (mAdapterProperties != null) return mAdapterProperties.getState(); 1403 return BluetoothAdapter.STATE_OFF; 1404 } 1405 1406 public boolean enable() { 1407 return enable(false); 1408 } 1409 1410 public boolean enableNoAutoConnect() { 1411 return enable (true); 1412 } 1413 1414 public synchronized boolean enable(boolean quietMode) { 1415 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1416 1417 // Enforce the user restriction for disallowing Bluetooth if it was set. 1418 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) { 1419 debugLog("enable() called when Bluetooth was disallowed"); 1420 return false; 1421 } 1422 1423 debugLog("enable() - Enable called with quiet mode status = " + mQuietmode); 1424 mQuietmode = quietMode; 1425 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON); 1426 mAdapterStateMachine.sendMessage(m); 1427 mBluetoothStartTime = System.currentTimeMillis(); 1428 return true; 1429 } 1430 1431 boolean disable() { 1432 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1433 1434 debugLog("disable() called..."); 1435 Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_OFF); 1436 mAdapterStateMachine.sendMessage(m); 1437 return true; 1438 } 1439 1440 String getAddress() { 1441 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1442 1443 String addrString = null; 1444 byte[] address = mAdapterProperties.getAddress(); 1445 return Utils.getAddressStringFromByte(address); 1446 } 1447 1448 ParcelUuid[] getUuids() { 1449 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1450 1451 return mAdapterProperties.getUuids(); 1452 } 1453 1454 public String getName() { 1455 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1456 "Need BLUETOOTH permission"); 1457 1458 try { 1459 return mAdapterProperties.getName(); 1460 } catch (Throwable t) { 1461 debugLog("getName() - Unexpected exception (" + t + ")"); 1462 } 1463 return null; 1464 } 1465 1466 boolean setName(String name) { 1467 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1468 "Need BLUETOOTH ADMIN permission"); 1469 1470 return mAdapterProperties.setName(name); 1471 } 1472 1473 int getScanMode() { 1474 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1475 1476 return mAdapterProperties.getScanMode(); 1477 } 1478 1479 boolean setScanMode(int mode, int duration) { 1480 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1481 1482 setDiscoverableTimeout(duration); 1483 1484 int newMode = convertScanModeToHal(mode); 1485 return mAdapterProperties.setScanMode(newMode); 1486 } 1487 1488 int getDiscoverableTimeout() { 1489 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1490 1491 return mAdapterProperties.getDiscoverableTimeout(); 1492 } 1493 1494 boolean setDiscoverableTimeout(int timeout) { 1495 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1496 1497 return mAdapterProperties.setDiscoverableTimeout(timeout); 1498 } 1499 1500 boolean startDiscovery() { 1501 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1502 "Need BLUETOOTH ADMIN permission"); 1503 1504 return startDiscoveryNative(); 1505 } 1506 1507 boolean cancelDiscovery() { 1508 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1509 "Need BLUETOOTH ADMIN permission"); 1510 1511 return cancelDiscoveryNative(); 1512 } 1513 1514 boolean isDiscovering() { 1515 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1516 1517 return mAdapterProperties.isDiscovering(); 1518 } 1519 1520 long getDiscoveryEndMillis() { 1521 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1522 1523 return mAdapterProperties.discoveryEndMillis(); 1524 } 1525 1526 public BluetoothDevice[] getBondedDevices() { 1527 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1528 return mAdapterProperties.getBondedDevices(); 1529 } 1530 1531 int getAdapterConnectionState() { 1532 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1533 return mAdapterProperties.getConnectionState(); 1534 } 1535 1536 int getProfileConnectionState(int profile) { 1537 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1538 1539 return mAdapterProperties.getProfileConnectionState(profile); 1540 } 1541 boolean sdpSearch(BluetoothDevice device,ParcelUuid uuid) { 1542 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1543 if(mSdpManager != null) { 1544 mSdpManager.sdpSearch(device,uuid); 1545 return true; 1546 } else { 1547 return false; 1548 } 1549 } 1550 1551 boolean createBond(BluetoothDevice device, int transport, OobData oobData) { 1552 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1553 "Need BLUETOOTH ADMIN permission"); 1554 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1555 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 1556 return false; 1557 } 1558 1559 mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); 1560 1561 // Pairing is unreliable while scanning, so cancel discovery 1562 // Note, remove this when native stack improves 1563 cancelDiscoveryNative(); 1564 1565 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 1566 msg.obj = device; 1567 msg.arg1 = transport; 1568 1569 if (oobData != null) { 1570 Bundle oobDataBundle = new Bundle(); 1571 oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData); 1572 msg.setData(oobDataBundle); 1573 } 1574 mBondStateMachine.sendMessage(msg); 1575 return true; 1576 } 1577 1578 public boolean isQuietModeEnabled() { 1579 debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode); 1580 return mQuietmode; 1581 } 1582 1583 public void updateUuids() { 1584 debugLog( "updateUuids() - Updating UUIDs for bonded devices"); 1585 BluetoothDevice[] bondedDevices = getBondedDevices(); 1586 if (bondedDevices == null) return; 1587 1588 for (BluetoothDevice device : bondedDevices) { 1589 mRemoteDevices.updateUuids(device); 1590 } 1591 } 1592 1593 boolean cancelBondProcess(BluetoothDevice device) { 1594 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1595 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1596 1597 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1598 if (deviceProp != null) { 1599 deviceProp.setBondingInitiatedLocally(false); 1600 } 1601 1602 return cancelBondNative(addr); 1603 } 1604 1605 boolean removeBond(BluetoothDevice device) { 1606 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1607 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1608 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 1609 return false; 1610 } 1611 deviceProp.setBondingInitiatedLocally(false); 1612 1613 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 1614 msg.obj = device; 1615 mBondStateMachine.sendMessage(msg); 1616 return true; 1617 } 1618 1619 int getBondState(BluetoothDevice device) { 1620 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1621 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1622 if (deviceProp == null) { 1623 return BluetoothDevice.BOND_NONE; 1624 } 1625 return deviceProp.getBondState(); 1626 } 1627 1628 boolean isBondingInitiatedLocally(BluetoothDevice device) { 1629 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1630 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1631 if (deviceProp == null) { 1632 return false; 1633 } 1634 return deviceProp.isBondingInitiatedLocally(); 1635 } 1636 1637 long getSupportedProfiles() { 1638 return Config.getSupportedProfilesBitMask(); 1639 } 1640 1641 int getConnectionState(BluetoothDevice device) { 1642 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1643 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1644 return getConnectionStateNative(addr); 1645 } 1646 1647 String getRemoteName(BluetoothDevice device) { 1648 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1649 if (mRemoteDevices == null) return null; 1650 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1651 if (deviceProp == null) return null; 1652 return deviceProp.getName(); 1653 } 1654 1655 int getRemoteType(BluetoothDevice device) { 1656 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1657 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1658 if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1659 return deviceProp.getDeviceType(); 1660 } 1661 1662 String getRemoteAlias(BluetoothDevice device) { 1663 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1664 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1665 if (deviceProp == null) return null; 1666 return deviceProp.getAlias(); 1667 } 1668 1669 boolean setRemoteAlias(BluetoothDevice device, String name) { 1670 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1671 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1672 if (deviceProp == null) return false; 1673 deviceProp.setAlias(device, name); 1674 return true; 1675 } 1676 1677 int getRemoteClass(BluetoothDevice device) { 1678 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1679 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1680 if (deviceProp == null) return 0; 1681 1682 return deviceProp.getBluetoothClass(); 1683 } 1684 1685 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1686 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1687 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1688 if (deviceProp == null) return null; 1689 return deviceProp.getUuids(); 1690 } 1691 1692 boolean fetchRemoteUuids(BluetoothDevice device) { 1693 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1694 mRemoteDevices.fetchUuids(device); 1695 return true; 1696 } 1697 1698 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1699 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1700 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1701 // Only allow setting a pin in bonding state, or bonded state in case of security upgrade. 1702 if (deviceProp == null 1703 || (deviceProp.getBondState() != BluetoothDevice.BOND_BONDING 1704 && deviceProp.getBondState() != BluetoothDevice.BOND_BONDED)) { 1705 return false; 1706 } 1707 1708 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1709 return pinReplyNative(addr, accept, len, pinCode); 1710 } 1711 1712 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1713 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1714 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1715 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1716 return false; 1717 } 1718 1719 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1720 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 1721 Utils.byteArrayToInt(passkey)); 1722 } 1723 1724 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1725 enforceCallingOrSelfPermission( 1726 BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission"); 1727 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1728 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1729 return false; 1730 } 1731 1732 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1733 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 1734 accept, 0); 1735 } 1736 1737 int getPhonebookAccessPermission(BluetoothDevice device) { 1738 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1739 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1740 Context.MODE_PRIVATE); 1741 if (!pref.contains(device.getAddress())) { 1742 return BluetoothDevice.ACCESS_UNKNOWN; 1743 } 1744 return pref.getBoolean(device.getAddress(), false) 1745 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1746 } 1747 1748 boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1749 enforceCallingOrSelfPermission( 1750 BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission"); 1751 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1752 Context.MODE_PRIVATE); 1753 SharedPreferences.Editor editor = pref.edit(); 1754 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1755 editor.remove(device.getAddress()); 1756 } else { 1757 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1758 } 1759 editor.apply(); 1760 return true; 1761 } 1762 1763 int getMessageAccessPermission(BluetoothDevice device) { 1764 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1765 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1766 Context.MODE_PRIVATE); 1767 if (!pref.contains(device.getAddress())) { 1768 return BluetoothDevice.ACCESS_UNKNOWN; 1769 } 1770 return pref.getBoolean(device.getAddress(), false) 1771 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1772 } 1773 1774 boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1775 enforceCallingOrSelfPermission( 1776 BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission"); 1777 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1778 Context.MODE_PRIVATE); 1779 SharedPreferences.Editor editor = pref.edit(); 1780 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1781 editor.remove(device.getAddress()); 1782 } else { 1783 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1784 } 1785 editor.apply(); 1786 return true; 1787 } 1788 1789 int getSimAccessPermission(BluetoothDevice device) { 1790 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1791 SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, 1792 Context.MODE_PRIVATE); 1793 if (!pref.contains(device.getAddress())) { 1794 return BluetoothDevice.ACCESS_UNKNOWN; 1795 } 1796 return pref.getBoolean(device.getAddress(), false) 1797 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1798 } 1799 1800 boolean setSimAccessPermission(BluetoothDevice device, int value) { 1801 enforceCallingOrSelfPermission( 1802 BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission"); 1803 SharedPreferences pref = getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, 1804 Context.MODE_PRIVATE); 1805 SharedPreferences.Editor editor = pref.edit(); 1806 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1807 editor.remove(device.getAddress()); 1808 } else { 1809 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1810 } 1811 editor.apply(); 1812 return true; 1813 } 1814 1815 void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) { 1816 // TODO(BT) permission check? 1817 // Since this is a binder call check if Bluetooth is on still 1818 if (getState() == BluetoothAdapter.STATE_OFF) return; 1819 1820 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 1821 1822 } 1823 1824 ParcelFileDescriptor connectSocket( 1825 BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag) { 1826 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1827 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), type, 1828 Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid()); 1829 if (fd < 0) { 1830 errorLog("Failed to connect socket"); 1831 return null; 1832 } 1833 return ParcelFileDescriptor.adoptFd(fd); 1834 } 1835 1836 ParcelFileDescriptor createSocketChannel( 1837 int type, String serviceName, ParcelUuid uuid, int port, int flag) { 1838 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1839 int fd = createSocketChannelNative( 1840 type, serviceName, Utils.uuidToByteArray(uuid), port, flag, Binder.getCallingUid()); 1841 if (fd < 0) { 1842 errorLog("Failed to create socket channel"); 1843 return null; 1844 } 1845 return ParcelFileDescriptor.adoptFd(fd); 1846 } 1847 1848 boolean factoryReset() { 1849 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1850 return factoryResetNative(); 1851 } 1852 1853 void registerCallback(IBluetoothCallback cb) { 1854 mCallbacks.register(cb); 1855 } 1856 1857 void unregisterCallback(IBluetoothCallback cb) { 1858 mCallbacks.unregister(cb); 1859 } 1860 1861 public int getNumOfAdvertisementInstancesSupported() { 1862 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1863 return mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 1864 } 1865 1866 public boolean isMultiAdvertisementSupported() { 1867 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1868 return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA; 1869 } 1870 1871 public boolean isRpaOffloadSupported() { 1872 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1873 return mAdapterProperties.isRpaOffloadSupported(); 1874 } 1875 1876 public int getNumOfOffloadedIrkSupported() { 1877 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1878 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 1879 } 1880 1881 public int getNumOfOffloadedScanFilterSupported() { 1882 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1883 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 1884 } 1885 1886 public int getOffloadedScanResultStorage() { 1887 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1888 return mAdapterProperties.getOffloadedScanResultStorage(); 1889 } 1890 1891 private boolean isActivityAndEnergyReportingSupported() { 1892 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1893 return mAdapterProperties.isActivityAndEnergyReportingSupported(); 1894 } 1895 1896 public boolean isLe2MPhySupported() { 1897 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1898 return mAdapterProperties.isLe2MPhySupported(); 1899 } 1900 1901 public boolean isLeCodedPhySupported() { 1902 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1903 return mAdapterProperties.isLeCodedPhySupported(); 1904 } 1905 1906 public boolean isLeExtendedAdvertisingSupported() { 1907 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1908 return mAdapterProperties.isLeExtendedAdvertisingSupported(); 1909 } 1910 1911 public boolean isLePeriodicAdvertisingSupported() { 1912 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1913 return mAdapterProperties.isLePeriodicAdvertisingSupported(); 1914 } 1915 1916 public int getLeMaximumAdvertisingDataLength() { 1917 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1918 return mAdapterProperties.getLeMaximumAdvertisingDataLength(); 1919 } 1920 1921 private BluetoothActivityEnergyInfo reportActivityInfo() { 1922 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1923 if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON || 1924 !mAdapterProperties.isActivityAndEnergyReportingSupported()) { 1925 return null; 1926 } 1927 1928 // Pull the data. The callback will notify mEnergyInfoLock. 1929 readEnergyInfo(); 1930 1931 synchronized (mEnergyInfoLock) { 1932 try { 1933 mEnergyInfoLock.wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); 1934 } catch (InterruptedException e) { 1935 // Just continue, the energy data may be stale but we won't miss anything next time 1936 // we query. 1937 } 1938 1939 final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo( 1940 SystemClock.elapsedRealtime(), 1941 mStackReportedState, 1942 mTxTimeTotalMs, mRxTimeTotalMs, mIdleTimeTotalMs, 1943 mEnergyUsedTotalVoltAmpSecMicro); 1944 1945 // Count the number of entries that have byte counts > 0 1946 int arrayLen = 0; 1947 for (int i = 0; i < mUidTraffic.size(); i++) { 1948 final UidTraffic traffic = mUidTraffic.valueAt(i); 1949 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 1950 arrayLen++; 1951 } 1952 } 1953 1954 // Copy the traffic objects whose byte counts are > 0 and reset the originals. 1955 final UidTraffic[] result = arrayLen > 0 ? new UidTraffic[arrayLen] : null; 1956 int putIdx = 0; 1957 for (int i = 0; i < mUidTraffic.size(); i++) { 1958 final UidTraffic traffic = mUidTraffic.valueAt(i); 1959 if (traffic.getTxBytes() != 0 || traffic.getRxBytes() != 0) { 1960 result[putIdx++] = traffic.clone(); 1961 traffic.setRxBytes(0); 1962 traffic.setTxBytes(0); 1963 } 1964 } 1965 1966 info.setUidTraffic(result); 1967 1968 // Read on clear values; a record of data is created with 1969 // timstamp and new samples are collected until read again 1970 mStackReportedState = 0; 1971 mTxTimeTotalMs = 0; 1972 mRxTimeTotalMs = 0; 1973 mIdleTimeTotalMs = 0; 1974 mEnergyUsedTotalVoltAmpSecMicro = 0; 1975 return info; 1976 } 1977 } 1978 1979 public int getTotalNumOfTrackableAdvertisements() { 1980 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1981 return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); 1982 } 1983 1984 public void onLeServiceUp() { 1985 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 1986 mAdapterStateMachine.sendMessage(m); 1987 } 1988 1989 public void onBrEdrDown() { 1990 Message m = mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 1991 mAdapterStateMachine.sendMessage(m); 1992 } 1993 1994 private static int convertScanModeToHal(int mode) { 1995 switch (mode) { 1996 case BluetoothAdapter.SCAN_MODE_NONE: 1997 return AbstractionLayer.BT_SCAN_MODE_NONE; 1998 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 1999 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 2000 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 2001 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2002 } 2003 // errorLog("Incorrect scan mode in convertScanModeToHal"); 2004 return -1; 2005 } 2006 2007 static int convertScanModeFromHal(int mode) { 2008 switch (mode) { 2009 case AbstractionLayer.BT_SCAN_MODE_NONE: 2010 return BluetoothAdapter.SCAN_MODE_NONE; 2011 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 2012 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 2013 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 2014 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 2015 } 2016 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 2017 return -1; 2018 } 2019 2020 // This function is called from JNI. It allows native code to set a single wake 2021 // alarm. If an alarm is already pending and a new request comes in, the alarm 2022 // will be rescheduled (i.e. the previously set alarm will be cancelled). 2023 private boolean setWakeAlarm(long delayMillis, boolean shouldWake) { 2024 synchronized (this) { 2025 if (mPendingAlarm != null) { 2026 mAlarmManager.cancel(mPendingAlarm); 2027 } 2028 2029 long wakeupTime = SystemClock.elapsedRealtime() + delayMillis; 2030 int type = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP 2031 : AlarmManager.ELAPSED_REALTIME; 2032 2033 Intent intent = new Intent(ACTION_ALARM_WAKEUP); 2034 mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); 2035 mAlarmManager.setExact(type, wakeupTime, mPendingAlarm); 2036 return true; 2037 } 2038 } 2039 2040 // This function is called from JNI. It allows native code to acquire a single wake lock. 2041 // If the wake lock is already held, this function returns success. Although this function 2042 // only supports acquiring a single wake lock at a time right now, it will eventually be 2043 // extended to allow acquiring an arbitrary number of wake locks. The current interface 2044 // takes |lockName| as a parameter in anticipation of that implementation. 2045 private boolean acquireWakeLock(String lockName) { 2046 synchronized (this) { 2047 if (mWakeLock == null) { 2048 mWakeLockName = lockName; 2049 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 2050 } 2051 2052 if (!mWakeLock.isHeld()) 2053 mWakeLock.acquire(); 2054 } 2055 return true; 2056 } 2057 2058 // This function is called from JNI. It allows native code to release a wake lock acquired 2059 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 2060 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 2061 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. 2062 private boolean releaseWakeLock(String lockName) { 2063 synchronized (this) { 2064 if (mWakeLock == null) { 2065 errorLog("Repeated wake lock release; aborting release: " + lockName); 2066 return false; 2067 } 2068 2069 if (mWakeLock.isHeld()) 2070 mWakeLock.release(); 2071 } 2072 return true; 2073 } 2074 2075 private void energyInfoCallback(int status, int ctrl_state, long tx_time, long rx_time, 2076 long idle_time, long energy_used, UidTraffic[] data) throws RemoteException { 2077 if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID 2078 && ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 2079 // Energy is product of mA, V and ms. If the chipset doesn't 2080 // report it, we have to compute it from time 2081 if (energy_used == 0) { 2082 try { 2083 final long txMah = Math.multiplyExact(tx_time, getTxCurrentMa()); 2084 final long rxMah = Math.multiplyExact(rx_time, getRxCurrentMa()); 2085 final long idleMah = Math.multiplyExact(idle_time, getIdleCurrentMa()); 2086 energy_used = (long) (Math.addExact(Math.addExact(txMah, rxMah), idleMah) 2087 * getOperatingVolt()); 2088 } catch (ArithmeticException e) { 2089 Slog.wtf(TAG, "overflow in bluetooth energy callback", e); 2090 // Energy is already 0 if the exception was thrown. 2091 } 2092 } 2093 2094 synchronized (mEnergyInfoLock) { 2095 mStackReportedState = ctrl_state; 2096 long totalTxTimeMs; 2097 long totalRxTimeMs; 2098 long totalIdleTimeMs; 2099 long totalEnergy; 2100 try { 2101 totalTxTimeMs = Math.addExact(mTxTimeTotalMs, tx_time); 2102 totalRxTimeMs = Math.addExact(mRxTimeTotalMs, rx_time); 2103 totalIdleTimeMs = Math.addExact(mIdleTimeTotalMs, idle_time); 2104 totalEnergy = Math.addExact(mEnergyUsedTotalVoltAmpSecMicro, energy_used); 2105 } catch (ArithmeticException e) { 2106 // This could be because we accumulated a lot of time, or we got a very strange 2107 // value from the controller (more likely). Discard this data. 2108 Slog.wtf(TAG, "overflow in bluetooth energy callback", e); 2109 totalTxTimeMs = mTxTimeTotalMs; 2110 totalRxTimeMs = mRxTimeTotalMs; 2111 totalIdleTimeMs = mIdleTimeTotalMs; 2112 totalEnergy = mEnergyUsedTotalVoltAmpSecMicro; 2113 } 2114 2115 mTxTimeTotalMs = totalTxTimeMs; 2116 mRxTimeTotalMs = totalRxTimeMs; 2117 mIdleTimeTotalMs = totalIdleTimeMs; 2118 mEnergyUsedTotalVoltAmpSecMicro = totalEnergy; 2119 2120 for (UidTraffic traffic : data) { 2121 UidTraffic existingTraffic = mUidTraffic.get(traffic.getUid()); 2122 if (existingTraffic == null) { 2123 mUidTraffic.put(traffic.getUid(), traffic); 2124 } else { 2125 existingTraffic.addRxBytes(traffic.getRxBytes()); 2126 existingTraffic.addTxBytes(traffic.getTxBytes()); 2127 } 2128 } 2129 mEnergyInfoLock.notifyAll(); 2130 } 2131 } 2132 2133 verboseLog("energyInfoCallback() status = " + status + "tx_time = " + tx_time + "rx_time = " 2134 + rx_time + "idle_time = " + idle_time + "energy_used = " + energy_used 2135 + "ctrl_state = " + ctrl_state + "traffic = " + Arrays.toString(data)); 2136 } 2137 2138 private int getIdleCurrentMa() { 2139 return getResources().getInteger(R.integer.config_bluetooth_idle_cur_ma); 2140 } 2141 2142 private int getTxCurrentMa() { 2143 return getResources().getInteger(R.integer.config_bluetooth_tx_cur_ma); 2144 } 2145 2146 private int getRxCurrentMa() { 2147 return getResources().getInteger(R.integer.config_bluetooth_rx_cur_ma); 2148 } 2149 2150 private double getOperatingVolt() { 2151 return getResources().getInteger(R.integer.config_bluetooth_operating_voltage_mv) / 1000.0; 2152 } 2153 2154 @Override 2155 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 2156 enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 2157 2158 if (args.length == 0) { 2159 writer.println("Skipping dump in APP SERVICES, see bluetooth_manager section."); 2160 writer.println("Use --print argument for dumpsys direct from AdapterService."); 2161 return; 2162 } 2163 2164 if (args.length > 0) { 2165 verboseLog( 2166 "dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args)); 2167 if (args[0].startsWith("--proto")) { 2168 if (args[0].equals("--proto-java-bin")) { 2169 dumpJava(fd); 2170 } else { 2171 dumpNative(fd, args); 2172 } 2173 return; 2174 } 2175 } 2176 2177 writer.println("Bonded devices:"); 2178 for (BluetoothDevice device : getBondedDevices()) { 2179 writer.println(" " + device.getAddress() + " [" + DEVICE_TYPE_NAMES[device.getType()] 2180 + "] " + device.getName()); 2181 } 2182 2183 // Dump profile information 2184 StringBuilder sb = new StringBuilder(); 2185 synchronized (mProfiles) { 2186 for (ProfileService profile : mProfiles) { 2187 profile.dump(sb); 2188 } 2189 } 2190 2191 writer.write(sb.toString()); 2192 writer.flush(); 2193 2194 dumpNative(fd, args); 2195 } 2196 2197 private void dumpJava(FileDescriptor fd) { 2198 BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog(); 2199 log.setNumBondedDevices(getBondedDevices().length); 2200 2201 for (ProfileService profile : mProfiles) { 2202 profile.dumpProto(log); 2203 } 2204 2205 try { 2206 FileOutputStream protoOut = new FileOutputStream(fd); 2207 String protoOutString = Base64.encodeToString(log.toByteArray(), Base64.DEFAULT); 2208 protoOut.write(protoOutString.getBytes(StandardCharsets.UTF_8)); 2209 protoOut.close(); 2210 } catch (IOException e) { 2211 errorLog("Unable to write Java protobuf to file descriptor."); 2212 } 2213 } 2214 2215 private void debugLog(String msg) { 2216 if (DBG) Log.d(TAG, msg); 2217 } 2218 2219 private void verboseLog(String msg) { 2220 if (VERBOSE) Log.v(TAG, msg); 2221 } 2222 2223 private void errorLog(String msg) { 2224 Log.e(TAG, msg); 2225 } 2226 2227 private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() { 2228 @Override 2229 public void onReceive(Context context, Intent intent) { 2230 synchronized (AdapterService.this) { 2231 mPendingAlarm = null; 2232 alarmFiredNative(); 2233 } 2234 } 2235 }; 2236 2237 private native static void classInitNative(); 2238 private native boolean initNative(); 2239 private native void cleanupNative(); 2240 /*package*/ native boolean enableNative(boolean startRestricted); 2241 /*package*/ native boolean disableNative(); 2242 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); 2243 /*package*/ native boolean getAdapterPropertiesNative(); 2244 /*package*/ native boolean getAdapterPropertyNative(int type); 2245 /*package*/ native boolean setAdapterPropertyNative(int type); 2246 /*package*/ native boolean setDevicePropertyNative(byte[] address, int type, byte[] val); 2247 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 2248 2249 /*package*/ native boolean createBondNative(byte[] address, int transport); 2250 /*package*/ native boolean createBondOutOfBandNative(byte[] address, int transport, OobData oobData); 2251 /*package*/ native boolean removeBondNative(byte[] address); 2252 /*package*/ native boolean cancelBondNative(byte[] address); 2253 /*package*/ native boolean sdpSearchNative(byte[] address, byte[] uuid); 2254 2255 /*package*/ native int getConnectionStateNative(byte[] address); 2256 2257 private native boolean startDiscoveryNative(); 2258 private native boolean cancelDiscoveryNative(); 2259 2260 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); 2261 private native boolean sspReplyNative(byte[] address, int type, boolean 2262 accept, int passkey); 2263 2264 /*package*/ native boolean getRemoteServicesNative(byte[] address); 2265 /*package*/ native boolean getRemoteMasInstancesNative(byte[] address); 2266 2267 private native int readEnergyInfo(); 2268 // TODO(BT) move this to ../btsock dir 2269 private native int connectSocketNative( 2270 byte[] address, int type, byte[] uuid, int port, int flag, int callingUid); 2271 private native int createSocketChannelNative( 2272 int type, String serviceName, byte[] uuid, int port, int flag, int callingUid); 2273 2274 /*package*/ native boolean factoryResetNative(); 2275 2276 private native void alarmFiredNative(); 2277 private native void dumpNative(FileDescriptor fd, String[] arguments); 2278 2279 private native void interopDatabaseClearNative(); 2280 private native void interopDatabaseAddNative(int feature, byte[] address, int length); 2281 2282 protected void finalize() { 2283 debugLog("finalize() - clean up object " + this); 2284 cleanup(); 2285 if (TRACE_REF) { 2286 synchronized (AdapterService.class) { 2287 sRefCount--; 2288 debugLog("finalize() - REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 2289 } 2290 } 2291 } 2292 2293 // Returns if this is a mock object. This is currently used in testing so that we may not call 2294 // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up 2295 // calling finalize() which in turn calls System.exit() and the process crashes. 2296 // 2297 // Mock this in your testing framework to return true to avoid the mentioned behavior. In 2298 // production this has no effect. 2299 public boolean isMock() { 2300 return false; 2301 } 2302} 2303