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