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