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 21 package com.android.bluetooth.btservice; 22 23 import android.app.AlarmManager; 24 import android.app.Application; 25 import android.app.PendingIntent; 26 import android.app.Service; 27 import android.bluetooth.BluetoothAdapter; 28 import android.bluetooth.BluetoothDevice; 29 import android.bluetooth.BluetoothProfile; 30 import android.bluetooth.BluetoothUuid; 31 import android.bluetooth.IBluetooth; 32 import android.bluetooth.IBluetoothCallback; 33 import android.bluetooth.IBluetoothManager; 34 import android.bluetooth.IBluetoothManagerCallback; 35 import android.bluetooth.BluetoothActivityEnergyInfo; 36 import android.content.BroadcastReceiver; 37 import android.content.ContentResolver; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.IntentFilter; 41 import android.content.SharedPreferences; 42 import android.os.Binder; 43 import android.os.Bundle; 44 import android.os.Handler; 45 import android.os.IBinder; 46 import android.os.Message; 47 import android.os.ParcelFileDescriptor; 48 import android.os.ParcelUuid; 49 import android.os.PowerManager; 50 import android.os.Process; 51 import android.os.RemoteCallbackList; 52 import android.os.RemoteException; 53 import android.os.SystemClock; 54 import android.provider.Settings; 55 import android.util.EventLog; 56 import android.util.Log; 57 import android.util.Pair; 58 59 import com.android.bluetooth.a2dp.A2dpService; 60 import com.android.bluetooth.hid.HidService; 61 import com.android.bluetooth.hfp.HeadsetService; 62 import com.android.bluetooth.hdp.HealthService; 63 import com.android.bluetooth.pan.PanService; 64 import com.android.bluetooth.Utils; 65 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; 66 import com.android.internal.R; 67 68 import java.io.FileDescriptor; 69 import java.io.IOException; 70 import java.util.ArrayList; 71 import java.util.HashMap; 72 import java.util.Set; 73 import java.util.Map; 74 import java.util.Iterator; 75 import java.util.Map.Entry; 76 import java.util.List; 77 78 import android.content.pm.PackageManager; 79 import android.os.ServiceManager; 80 81 public class AdapterService extends Service { 82 private static final String TAG = "BluetoothAdapterService"; 83 private static final boolean DBG = false; 84 private static final boolean TRACE_REF = true; 85 private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; 86 private static final int MIN_OFFLOADED_FILTERS = 10; 87 private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; 88 //For Debugging only 89 private static int sRefCount=0; 90 91 private int mStackReportedState; 92 private int mTxTimeTotalMs; 93 private int mRxTimeTotalMs; 94 private int mIdleTimeTotalMs; 95 private int mEnergyUsedTotalVoltAmpSecMicro; 96 97 private final ArrayList<ProfileService> mProfiles = new ArrayList<ProfileService>(); 98 99 public static final String ACTION_LOAD_ADAPTER_PROPERTIES = 100 "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; 101 public static final String ACTION_SERVICE_STATE_CHANGED = 102 "com.android.bluetooth.btservice.action.STATE_CHANGED"; 103 public static final String EXTRA_ACTION="action"; 104 public static final int PROFILE_CONN_CONNECTED = 1; 105 public static final int PROFILE_CONN_REJECTED = 2; 106 107 private static final String ACTION_ALARM_WAKEUP = 108 "com.android.bluetooth.btservice.action.ALARM_WAKEUP"; 109 110 static final String BLUETOOTH_ADMIN_PERM = 111 android.Manifest.permission.BLUETOOTH_ADMIN; 112 public static final String BLUETOOTH_PRIVILEGED = 113 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 114 static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 115 static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; 116 117 private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = 118 "phonebook_access_permission"; 119 private static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = 120 "message_access_permission"; 121 122 private static final int ADAPTER_SERVICE_TYPE=Service.START_STICKY; 123 124 static { classInitNative()125 classInitNative(); 126 } 127 128 private static AdapterService sAdapterService; getAdapterService()129 public static synchronized AdapterService getAdapterService(){ 130 if (sAdapterService != null && !sAdapterService.mCleaningUp) { 131 Log.d(TAG, "getAdapterService() - returning " + sAdapterService); 132 return sAdapterService; 133 } 134 if (DBG) { 135 if (sAdapterService == null) { 136 Log.d(TAG, "getAdapterService() - Service not available"); 137 } else if (sAdapterService.mCleaningUp) { 138 Log.d(TAG,"getAdapterService() - Service is cleaning up"); 139 } 140 } 141 return null; 142 } 143 setAdapterService(AdapterService instance)144 private static synchronized void setAdapterService(AdapterService instance) { 145 if (instance != null && !instance.mCleaningUp) { 146 if (DBG) Log.d(TAG, "setAdapterService() - set to: " + sAdapterService); 147 sAdapterService = instance; 148 } else { 149 if (DBG) { 150 if (sAdapterService == null) { 151 Log.d(TAG, "setAdapterService() - Service not available"); 152 } else if (sAdapterService.mCleaningUp) { 153 Log.d(TAG,"setAdapterService() - Service is cleaning up"); 154 } 155 } 156 } 157 } 158 clearAdapterService()159 private static synchronized void clearAdapterService() { 160 sAdapterService = null; 161 } 162 163 private AdapterProperties mAdapterProperties; 164 private AdapterState mAdapterStateMachine; 165 private BondStateMachine mBondStateMachine; 166 private JniCallbacks mJniCallbacks; 167 private RemoteDevices mRemoteDevices; 168 private boolean mProfilesStarted; 169 private boolean mNativeAvailable; 170 private boolean mCleaningUp; 171 private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>(); 172 private RemoteCallbackList<IBluetoothCallback> mCallbacks;//Only BluetoothManagerService should be registered 173 private int mCurrentRequestId; 174 private boolean mQuietmode = false; 175 176 private AlarmManager mAlarmManager; 177 private PendingIntent mPendingAlarm; 178 private PowerManager mPowerManager; 179 private PowerManager.WakeLock mWakeLock; 180 private String mWakeLockName; 181 AdapterService()182 public AdapterService() { 183 super(); 184 if (TRACE_REF) { 185 synchronized (AdapterService.class) { 186 sRefCount++; 187 debugLog("AdapterService() - REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount); 188 } 189 } 190 } 191 onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState)192 public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 193 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED); 194 m.obj = device; 195 m.arg1 = profileId; 196 m.arg2 = newState; 197 Bundle b = new Bundle(1); 198 b.putInt("prevState", prevState); 199 m.setData(b); 200 mHandler.sendMessage(m); 201 } 202 initProfilePriorities(BluetoothDevice device, ParcelUuid[] mUuids)203 public void initProfilePriorities(BluetoothDevice device, ParcelUuid[] mUuids) { 204 if(mUuids == null) return; 205 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_INIT_PRIORITIES); 206 m.obj = device; 207 m.arg1 = mUuids.length; 208 Bundle b = new Bundle(1); 209 for(int i=0; i<mUuids.length; i++) { 210 b.putParcelable("uuids" + i, mUuids[i]); 211 } 212 m.setData(b); 213 mHandler.sendMessage(m); 214 } 215 processInitProfilePriorities(BluetoothDevice device, ParcelUuid[] uuids)216 private void processInitProfilePriorities (BluetoothDevice device, ParcelUuid[] uuids){ 217 HidService hidService = HidService.getHidService(); 218 A2dpService a2dpService = A2dpService.getA2dpService(); 219 HeadsetService headsetService = HeadsetService.getHeadsetService(); 220 221 // Set profile priorities only for the profiles discovered on the remote device. 222 // This avoids needless auto-connect attempts to profiles non-existent on the remote device 223 if ((hidService != null) && 224 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) || 225 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) && 226 (hidService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){ 227 hidService.setPriority(device,BluetoothProfile.PRIORITY_ON); 228 } 229 230 // If we do not have a stored priority for A2DP then default to on. 231 if ((a2dpService != null) && 232 (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink) || 233 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AdvAudioDist)) && 234 (a2dpService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED)){ 235 a2dpService.setPriority(device,BluetoothProfile.PRIORITY_ON); 236 } 237 238 if ((headsetService != null) && 239 ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP) || 240 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) && 241 (headsetService.getPriority(device) == BluetoothProfile.PRIORITY_UNDEFINED))){ 242 headsetService.setPriority(device,BluetoothProfile.PRIORITY_ON); 243 } 244 } 245 processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState)246 private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) { 247 if (((profileId == BluetoothProfile.A2DP) ||(profileId == BluetoothProfile.HEADSET)) && 248 (newState == BluetoothProfile.STATE_CONNECTED)){ 249 debugLog( "Profile connected. Schedule missing profile connection if any"); 250 connectOtherProfile(device, PROFILE_CONN_CONNECTED); 251 setProfileAutoConnectionPriority(device, profileId); 252 } 253 IBluetooth.Stub binder = mBinder; 254 if (binder != null) { 255 try { 256 binder.sendConnectionStateChange(device, profileId, newState,prevState); 257 } catch (RemoteException re) { 258 errorLog("" + re); 259 } 260 } 261 } 262 addProfile(ProfileService profile)263 public void addProfile(ProfileService profile) { 264 synchronized (mProfiles) { 265 mProfiles.add(profile); 266 } 267 } 268 removeProfile(ProfileService profile)269 public void removeProfile(ProfileService profile) { 270 synchronized (mProfiles) { 271 mProfiles.remove(profile); 272 } 273 } 274 onProfileServiceStateChanged(String serviceName, int state)275 public void onProfileServiceStateChanged(String serviceName, int state) { 276 Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); 277 m.obj=serviceName; 278 m.arg1 = state; 279 mHandler.sendMessage(m); 280 } 281 processProfileServiceStateChanged(String serviceName, int state)282 private void processProfileServiceStateChanged(String serviceName, int state) { 283 boolean doUpdate=false; 284 boolean isTurningOn; 285 boolean isTurningOff; 286 287 synchronized (mProfileServicesState) { 288 Integer prevState = mProfileServicesState.get(serviceName); 289 if (prevState != null && prevState != state) { 290 mProfileServicesState.put(serviceName,state); 291 doUpdate=true; 292 } 293 } 294 debugLog("onProfileServiceStateChange() serviceName=" + serviceName 295 + ", state=" + state +", doUpdate=" + doUpdate); 296 297 if (!doUpdate) { 298 return; 299 } 300 301 synchronized (mAdapterStateMachine) { 302 isTurningOff = mAdapterStateMachine.isTurningOff(); 303 isTurningOn = mAdapterStateMachine.isTurningOn(); 304 } 305 306 if (isTurningOff) { 307 //Process stop or disable pending 308 //Check if all services are stopped if so, do cleanup 309 synchronized (mProfileServicesState) { 310 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 311 while (i.hasNext()) { 312 Map.Entry<String,Integer> entry = i.next(); 313 if (BluetoothAdapter.STATE_OFF != entry.getValue()) { 314 debugLog("onProfileServiceStateChange() - Profile still running: " 315 + entry.getKey()); 316 return; 317 } 318 } 319 } 320 debugLog("onProfileServiceStateChange() - All profile services stopped..."); 321 //Send message to state machine 322 mProfilesStarted=false; 323 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STOPPED)); 324 } else if (isTurningOn) { 325 //Process start pending 326 //Check if all services are started if so, update state 327 synchronized (mProfileServicesState) { 328 Iterator<Map.Entry<String,Integer>> i = mProfileServicesState.entrySet().iterator(); 329 while (i.hasNext()) { 330 Map.Entry<String,Integer> entry = i.next(); 331 if (BluetoothAdapter.STATE_ON != entry.getValue()) { 332 debugLog("onProfileServiceStateChange() - Profile still not running:" 333 + entry.getKey()); 334 return; 335 } 336 } 337 } 338 debugLog("onProfileServiceStateChange() - All profile services started."); 339 mProfilesStarted=true; 340 //Send message to state machine 341 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED)); 342 } 343 } 344 345 @Override onCreate()346 public void onCreate() { 347 super.onCreate(); 348 debugLog("onCreate()"); 349 mBinder = new AdapterServiceBinder(this); 350 mAdapterProperties = new AdapterProperties(this); 351 mAdapterStateMachine = AdapterState.make(this, mAdapterProperties); 352 mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties); 353 initNative(); 354 mNativeAvailable=true; 355 mCallbacks = new RemoteCallbackList<IBluetoothCallback>(); 356 //Load the name and address 357 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR); 358 getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME); 359 mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 360 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 361 362 registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); 363 } 364 365 @Override onBind(Intent intent)366 public IBinder onBind(Intent intent) { 367 debugLog("onBind()"); 368 return mBinder; 369 } onUnbind(Intent intent)370 public boolean onUnbind(Intent intent) { 371 debugLog("onUnbind() - calling cleanup"); 372 cleanup(); 373 return super.onUnbind(intent); 374 } 375 onDestroy()376 public void onDestroy() { 377 debugLog("onDestroy()"); 378 } 379 processStart()380 void processStart() { 381 debugLog("processStart()"); 382 Class[] supportedProfileServices = Config.getSupportedProfiles(); 383 //Initialize data objects 384 for (int i=0; i < supportedProfileServices.length;i++) { 385 mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF); 386 } 387 mRemoteDevices = new RemoteDevices(this); 388 mAdapterProperties.init(mRemoteDevices); 389 390 debugLog("processStart() - Make Bond State Machine"); 391 mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices); 392 393 mJniCallbacks.init(mBondStateMachine,mRemoteDevices); 394 395 //FIXME: Set static instance here??? 396 setAdapterService(this); 397 398 //Start profile services 399 if (!mProfilesStarted && supportedProfileServices.length >0) { 400 //Startup all profile services 401 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON); 402 }else { 403 debugLog("processStart() - Profile Services alreay started"); 404 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED)); 405 } 406 } 407 startBluetoothDisable()408 void startBluetoothDisable() { 409 mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE)); 410 } 411 stopProfileServices()412 boolean stopProfileServices() { 413 Class[] supportedProfileServices = Config.getSupportedProfiles(); 414 if (mProfilesStarted && supportedProfileServices.length>0) { 415 setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_OFF); 416 return true; 417 } 418 debugLog("stopProfileServices() - No profiles services to stop or already stopped."); 419 return false; 420 } 421 updateAdapterState(int prevState, int newState)422 void updateAdapterState(int prevState, int newState){ 423 if (mCallbacks !=null) { 424 int n=mCallbacks.beginBroadcast(); 425 debugLog("updateAdapterState() - Broadcasting state to " + n + " receivers."); 426 for (int i=0; i <n;i++) { 427 try { 428 mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState,newState); 429 } catch (RemoteException e) { 430 debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")"); 431 } 432 } 433 mCallbacks.finishBroadcast(); 434 } 435 } 436 cleanup()437 void cleanup () { 438 debugLog("cleanup()"); 439 if (mCleaningUp) { 440 errorLog("cleanup() - Service already starting to cleanup, ignoring request..."); 441 return; 442 } 443 444 mCleaningUp = true; 445 446 unregisterReceiver(mAlarmBroadcastReceiver); 447 448 if (mPendingAlarm != null) { 449 mAlarmManager.cancel(mPendingAlarm); 450 mPendingAlarm = null; 451 } 452 453 // This wake lock release may also be called concurrently by 454 // {@link #releaseWakeLock(String lockName)}, so a synchronization is needed here. 455 synchronized (this) { 456 if (mWakeLock != null) { 457 mWakeLock.release(); 458 mWakeLock = null; 459 } 460 } 461 462 if (mAdapterStateMachine != null) { 463 mAdapterStateMachine.doQuit(); 464 mAdapterStateMachine.cleanup(); 465 } 466 467 if (mBondStateMachine != null) { 468 mBondStateMachine.doQuit(); 469 mBondStateMachine.cleanup(); 470 } 471 472 if (mRemoteDevices != null) { 473 mRemoteDevices.cleanup(); 474 } 475 476 if (mNativeAvailable) { 477 debugLog("cleanup() - Cleaning up adapter native"); 478 cleanupNative(); 479 mNativeAvailable=false; 480 } 481 482 if (mAdapterProperties != null) { 483 mAdapterProperties.cleanup(); 484 } 485 486 if (mJniCallbacks != null) { 487 mJniCallbacks.cleanup(); 488 } 489 490 if (mProfileServicesState != null) { 491 mProfileServicesState.clear(); 492 } 493 494 clearAdapterService(); 495 496 if (mBinder != null) { 497 mBinder.cleanup(); 498 mBinder = null; //Do not remove. Otherwise Binder leak! 499 } 500 501 if (mCallbacks !=null) { 502 mCallbacks.kill(); 503 } 504 505 debugLog("cleanup() - Bluetooth process exited normally."); 506 System.exit(0); 507 } 508 509 private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1; 510 private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20; 511 private static final int MESSAGE_CONNECT_OTHER_PROFILES = 30; 512 private static final int MESSAGE_PROFILE_INIT_PRIORITIES=40; 513 private static final int MESSAGE_SET_WAKE_ALARM = 100; 514 private static final int MESSAGE_RELEASE_WAKE_ALARM = 110; 515 private static final int CONNECT_OTHER_PROFILES_TIMEOUT= 6000; 516 517 private final Handler mHandler = new Handler() { 518 @Override 519 public void handleMessage(Message msg) { 520 debugLog("handleMessage() - Message: " + msg.what); 521 522 switch (msg.what) { 523 case MESSAGE_PROFILE_SERVICE_STATE_CHANGED: { 524 debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED"); 525 processProfileServiceStateChanged((String) msg.obj, msg.arg1); 526 } 527 break; 528 case MESSAGE_PROFILE_CONNECTION_STATE_CHANGED: { 529 debugLog( "handleMessage() - MESSAGE_PROFILE_CONNECTION_STATE_CHANGED"); 530 processProfileStateChanged((BluetoothDevice) msg.obj, msg.arg1,msg.arg2, msg.getData().getInt("prevState",BluetoothAdapter.ERROR)); 531 } 532 break; 533 case MESSAGE_PROFILE_INIT_PRIORITIES: { 534 debugLog( "handleMessage() - MESSAGE_PROFILE_INIT_PRIORITIES"); 535 ParcelUuid[] mUuids = new ParcelUuid[msg.arg1]; 536 for(int i=0; i<mUuids.length; i++) { 537 mUuids[i] = msg.getData().getParcelable("uuids" + i); 538 } 539 processInitProfilePriorities((BluetoothDevice) msg.obj, 540 mUuids); 541 } 542 break; 543 case MESSAGE_CONNECT_OTHER_PROFILES: { 544 debugLog( "handleMessage() - MESSAGE_CONNECT_OTHER_PROFILES"); 545 processConnectOtherProfiles((BluetoothDevice) msg.obj,msg.arg1); 546 } 547 break; 548 case MESSAGE_SET_WAKE_ALARM: { 549 debugLog( "handleMessage() - MESSAGE_SET_WAKE_ALARM"); 550 processSetWakeAlarm((Long) msg.obj, msg.arg1); 551 } 552 break; 553 case MESSAGE_RELEASE_WAKE_ALARM: { 554 debugLog( "handleMessage() - MESSAGE_RELEASE_WAKE_ALARM"); 555 mPendingAlarm = null; 556 alarmFiredNative(); 557 } 558 break; 559 } 560 } 561 }; 562 563 @SuppressWarnings("rawtypes") setProfileServiceState(Class[] services, int state)564 private void setProfileServiceState(Class[] services, int state) { 565 if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { 566 debugLog("setProfileServiceState() - Invalid state, leaving..."); 567 return; 568 } 569 570 int expectedCurrentState= BluetoothAdapter.STATE_OFF; 571 int pendingState = BluetoothAdapter.STATE_TURNING_ON; 572 if (state == BluetoothAdapter.STATE_OFF) { 573 expectedCurrentState= BluetoothAdapter.STATE_ON; 574 pendingState = BluetoothAdapter.STATE_TURNING_OFF; 575 } 576 577 for (int i=0; i <services.length;i++) { 578 String serviceName = services[i].getName(); 579 Integer serviceState = mProfileServicesState.get(serviceName); 580 if(serviceState != null && serviceState != expectedCurrentState) { 581 debugLog("setProfileServiceState() - Unable to " 582 + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" ) 583 + " service " + serviceName 584 + ". Invalid state: " + serviceState); 585 continue; 586 } 587 588 debugLog("setProfileServiceState() - " 589 + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting") 590 + " service " + serviceName); 591 592 mProfileServicesState.put(serviceName,pendingState); 593 Intent intent = new Intent(this,services[i]); 594 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED); 595 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state); 596 startService(intent); 597 } 598 } 599 isAvailable()600 private boolean isAvailable() { 601 return !mCleaningUp; 602 } 603 604 /** 605 * Handlers for incoming service calls 606 */ 607 private AdapterServiceBinder mBinder; 608 609 /** 610 * The Binder implementation must be declared to be a static class, with 611 * the AdapterService instance passed in the constructor. Furthermore, 612 * when the AdapterService shuts down, the reference to the AdapterService 613 * must be explicitly removed. 614 * 615 * Otherwise, a memory leak can occur from repeated starting/stopping the 616 * service...Please refer to android.os.Binder for further details on 617 * why an inner instance class should be avoided. 618 * 619 */ 620 private static class AdapterServiceBinder extends IBluetooth.Stub { 621 private AdapterService mService; 622 AdapterServiceBinder(AdapterService svc)623 public AdapterServiceBinder(AdapterService svc) { 624 mService = svc; 625 } cleanup()626 public boolean cleanup() { 627 mService = null; 628 return true; 629 } 630 getService()631 public AdapterService getService() { 632 if (mService != null && mService.isAvailable()) { 633 return mService; 634 } 635 return null; 636 } isEnabled()637 public boolean isEnabled() { 638 // don't check caller, may be called from system UI 639 AdapterService service = getService(); 640 if (service == null) return false; 641 return service.isEnabled(); 642 } 643 getState()644 public int getState() { 645 // don't check caller, may be called from system UI 646 AdapterService service = getService(); 647 if (service == null) return BluetoothAdapter.STATE_OFF; 648 return service.getState(); 649 } 650 enable()651 public boolean enable() { 652 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 653 (!Utils.checkCaller())) { 654 Log.w(TAG, "enable() - Not allowed for non-active user and non system user"); 655 return false; 656 } 657 658 AdapterService service = getService(); 659 if (service == null) return false; 660 return service.enable(); 661 } 662 enableNoAutoConnect()663 public boolean enableNoAutoConnect() { 664 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 665 (!Utils.checkCaller())) { 666 Log.w(TAG, "enableNoAuto() - Not allowed for non-active user and non system user"); 667 return false; 668 } 669 670 AdapterService service = getService(); 671 if (service == null) return false; 672 return service.enableNoAutoConnect(); 673 } 674 disable()675 public boolean disable() { 676 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 677 (!Utils.checkCaller())) { 678 Log.w(TAG, "disable() - Not allowed for non-active user and non system user"); 679 return false; 680 } 681 682 AdapterService service = getService(); 683 if (service == null) return false; 684 return service.disable(); 685 } 686 getAddress()687 public String getAddress() { 688 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 689 (!Utils.checkCallerAllowManagedProfiles(mService))) { 690 Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user"); 691 return null; 692 } 693 694 AdapterService service = getService(); 695 if (service == null) return null; 696 return service.getAddress(); 697 } 698 getUuids()699 public ParcelUuid[] getUuids() { 700 if (!Utils.checkCaller()) { 701 Log.w(TAG, "getUuids() - Not allowed for non-active user"); 702 return new ParcelUuid[0]; 703 } 704 705 AdapterService service = getService(); 706 if (service == null) return new ParcelUuid[0]; 707 return service.getUuids(); 708 } 709 getName()710 public String getName() { 711 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 712 (!Utils.checkCaller())) { 713 Log.w(TAG, "getName() - Not allowed for non-active user and non system user"); 714 return null; 715 } 716 717 AdapterService service = getService(); 718 if (service == null) return null; 719 return service.getName(); 720 } 721 setName(String name)722 public boolean setName(String name) { 723 if (!Utils.checkCaller()) { 724 Log.w(TAG, "setName() - Not allowed for non-active user"); 725 return false; 726 } 727 728 AdapterService service = getService(); 729 if (service == null) return false; 730 return service.setName(name); 731 } 732 getScanMode()733 public int getScanMode() { 734 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 735 Log.w(TAG, "getScanMode() - Not allowed for non-active user"); 736 return BluetoothAdapter.SCAN_MODE_NONE; 737 } 738 739 AdapterService service = getService(); 740 if (service == null) return BluetoothAdapter.SCAN_MODE_NONE; 741 return service.getScanMode(); 742 } 743 setScanMode(int mode, int duration)744 public boolean setScanMode(int mode, int duration) { 745 if (!Utils.checkCaller()) { 746 Log.w(TAG, "setScanMode() - Not allowed for non-active user"); 747 return false; 748 } 749 750 AdapterService service = getService(); 751 if (service == null) return false; 752 return service.setScanMode(mode,duration); 753 } 754 getDiscoverableTimeout()755 public int getDiscoverableTimeout() { 756 if (!Utils.checkCaller()) { 757 Log.w(TAG, "getDiscoverableTimeout() - Not allowed for non-active user"); 758 return 0; 759 } 760 761 AdapterService service = getService(); 762 if (service == null) return 0; 763 return service.getDiscoverableTimeout(); 764 } 765 setDiscoverableTimeout(int timeout)766 public boolean setDiscoverableTimeout(int timeout) { 767 if (!Utils.checkCaller()) { 768 Log.w(TAG, "setDiscoverableTimeout() - Not allowed for non-active user"); 769 return false; 770 } 771 772 AdapterService service = getService(); 773 if (service == null) return false; 774 return service.setDiscoverableTimeout(timeout); 775 } 776 startDiscovery()777 public boolean startDiscovery() { 778 if (!Utils.checkCaller()) { 779 Log.w(TAG, "startDiscovery() - Not allowed for non-active user"); 780 return false; 781 } 782 783 AdapterService service = getService(); 784 if (service == null) return false; 785 return service.startDiscovery(); 786 } 787 cancelDiscovery()788 public boolean cancelDiscovery() { 789 if (!Utils.checkCaller()) { 790 Log.w(TAG, "cancelDiscovery() - Not allowed for non-active user"); 791 return false; 792 } 793 794 AdapterService service = getService(); 795 if (service == null) return false; 796 return service.cancelDiscovery(); 797 } isDiscovering()798 public boolean isDiscovering() { 799 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 800 Log.w(TAG, "isDiscovering() - Not allowed for non-active user"); 801 return false; 802 } 803 804 AdapterService service = getService(); 805 if (service == null) return false; 806 return service.isDiscovering(); 807 } 808 getBondedDevices()809 public BluetoothDevice[] getBondedDevices() { 810 // don't check caller, may be called from system UI 811 AdapterService service = getService(); 812 if (service == null) return new BluetoothDevice[0]; 813 return service.getBondedDevices(); 814 } 815 getAdapterConnectionState()816 public int getAdapterConnectionState() { 817 // don't check caller, may be called from system UI 818 AdapterService service = getService(); 819 if (service == null) return BluetoothAdapter.STATE_DISCONNECTED; 820 return service.getAdapterConnectionState(); 821 } 822 getProfileConnectionState(int profile)823 public int getProfileConnectionState(int profile) { 824 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 825 Log.w(TAG, "getProfileConnectionState- Not allowed for non-active user"); 826 return BluetoothProfile.STATE_DISCONNECTED; 827 } 828 829 AdapterService service = getService(); 830 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 831 return service.getProfileConnectionState(profile); 832 } 833 createBond(BluetoothDevice device, int transport)834 public boolean createBond(BluetoothDevice device, int transport) { 835 if (!Utils.checkCaller()) { 836 Log.w(TAG, "createBond() - Not allowed for non-active user"); 837 return false; 838 } 839 840 AdapterService service = getService(); 841 if (service == null) return false; 842 return service.createBond(device, transport); 843 } 844 cancelBondProcess(BluetoothDevice device)845 public boolean cancelBondProcess(BluetoothDevice device) { 846 if (!Utils.checkCaller()) { 847 Log.w(TAG, "cancelBondProcess() - Not allowed for non-active user"); 848 return false; 849 } 850 851 AdapterService service = getService(); 852 if (service == null) return false; 853 return service.cancelBondProcess(device); 854 } 855 removeBond(BluetoothDevice device)856 public boolean removeBond(BluetoothDevice device) { 857 if (!Utils.checkCaller()) { 858 Log.w(TAG, "removeBond() - Not allowed for non-active user"); 859 return false; 860 } 861 862 AdapterService service = getService(); 863 if (service == null) return false; 864 return service.removeBond(device); 865 } 866 getBondState(BluetoothDevice device)867 public int getBondState(BluetoothDevice device) { 868 // don't check caller, may be called from system UI 869 AdapterService service = getService(); 870 if (service == null) return BluetoothDevice.BOND_NONE; 871 return service.getBondState(device); 872 } 873 getConnectionState(BluetoothDevice device)874 public int getConnectionState(BluetoothDevice device) { 875 AdapterService service = getService(); 876 if (service == null) return 0; 877 return service.getConnectionState(device); 878 } 879 getRemoteName(BluetoothDevice device)880 public String getRemoteName(BluetoothDevice device) { 881 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 882 Log.w(TAG, "getRemoteName() - Not allowed for non-active user"); 883 return null; 884 } 885 886 AdapterService service = getService(); 887 if (service == null) return null; 888 return service.getRemoteName(device); 889 } 890 getRemoteType(BluetoothDevice device)891 public int getRemoteType(BluetoothDevice device) { 892 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 893 Log.w(TAG, "getRemoteType() - Not allowed for non-active user"); 894 return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 895 } 896 897 AdapterService service = getService(); 898 if (service == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 899 return service.getRemoteType(device); 900 } 901 getRemoteAlias(BluetoothDevice device)902 public String getRemoteAlias(BluetoothDevice device) { 903 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 904 Log.w(TAG, "getRemoteAlias() - Not allowed for non-active user"); 905 return null; 906 } 907 908 AdapterService service = getService(); 909 if (service == null) return null; 910 return service.getRemoteAlias(device); 911 } 912 setRemoteAlias(BluetoothDevice device, String name)913 public boolean setRemoteAlias(BluetoothDevice device, String name) { 914 if (!Utils.checkCaller()) { 915 Log.w(TAG, "setRemoteAlias() - Not allowed for non-active user"); 916 return false; 917 } 918 919 AdapterService service = getService(); 920 if (service == null) return false; 921 return service.setRemoteAlias(device, name); 922 } 923 getRemoteClass(BluetoothDevice device)924 public int getRemoteClass(BluetoothDevice device) { 925 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 926 Log.w(TAG, "getRemoteClass() - Not allowed for non-active user"); 927 return 0; 928 } 929 930 AdapterService service = getService(); 931 if (service == null) return 0; 932 return service.getRemoteClass(device); 933 } 934 getRemoteUuids(BluetoothDevice device)935 public ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 936 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 937 Log.w(TAG, "getRemoteUuids() - Not allowed for non-active user"); 938 return new ParcelUuid[0]; 939 } 940 941 AdapterService service = getService(); 942 if (service == null) return new ParcelUuid[0]; 943 return service.getRemoteUuids(device); 944 } 945 fetchRemoteUuids(BluetoothDevice device)946 public boolean fetchRemoteUuids(BluetoothDevice device) { 947 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 948 Log.w(TAG, "fetchRemoteUuids() - Not allowed for non-active user"); 949 return false; 950 } 951 952 AdapterService service = getService(); 953 if (service == null) return false; 954 return service.fetchRemoteUuids(device); 955 } 956 fetchRemoteMasInstances(BluetoothDevice device)957 public boolean fetchRemoteMasInstances(BluetoothDevice device) { 958 if (!Utils.checkCaller()) { 959 Log.w(TAG,"fetchMasInstances(): not allowed for non-active user"); 960 return false; 961 } 962 963 AdapterService service = getService(); 964 if (service == null) return false; 965 return service.fetchRemoteMasInstances(device); 966 } 967 setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode)968 public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 969 if (!Utils.checkCaller()) { 970 Log.w(TAG, "setPin() - Not allowed for non-active user"); 971 return false; 972 } 973 974 AdapterService service = getService(); 975 if (service == null) return false; 976 return service.setPin(device, accept, len, pinCode); 977 } 978 setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey)979 public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 980 if (!Utils.checkCaller()) { 981 Log.w(TAG, "setPasskey() - Not allowed for non-active user"); 982 return false; 983 } 984 985 AdapterService service = getService(); 986 if (service == null) return false; 987 return service.setPasskey(device, accept, len, passkey); 988 } 989 setPairingConfirmation(BluetoothDevice device, boolean accept)990 public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 991 if (!Utils.checkCaller()) { 992 Log.w(TAG, "setPairingConfirmation() - Not allowed for non-active user"); 993 return false; 994 } 995 996 AdapterService service = getService(); 997 if (service == null) return false; 998 return service.setPairingConfirmation(device, accept); 999 } 1000 getPhonebookAccessPermission(BluetoothDevice device)1001 public int getPhonebookAccessPermission(BluetoothDevice device) { 1002 if (!Utils.checkCaller()) { 1003 Log.w(TAG, "getPhonebookAccessPermission() - Not allowed for non-active user"); 1004 return BluetoothDevice.ACCESS_UNKNOWN; 1005 } 1006 1007 AdapterService service = getService(); 1008 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1009 return service.getPhonebookAccessPermission(device); 1010 } 1011 setPhonebookAccessPermission(BluetoothDevice device, int value)1012 public boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1013 if (!Utils.checkCaller()) { 1014 Log.w(TAG, "setPhonebookAccessPermission() - Not allowed for non-active user"); 1015 return false; 1016 } 1017 1018 AdapterService service = getService(); 1019 if (service == null) return false; 1020 return service.setPhonebookAccessPermission(device, value); 1021 } 1022 getMessageAccessPermission(BluetoothDevice device)1023 public int getMessageAccessPermission(BluetoothDevice device) { 1024 if (!Utils.checkCaller()) { 1025 Log.w(TAG, "getMessageAccessPermission() - Not allowed for non-active user"); 1026 return BluetoothDevice.ACCESS_UNKNOWN; 1027 } 1028 1029 AdapterService service = getService(); 1030 if (service == null) return BluetoothDevice.ACCESS_UNKNOWN; 1031 return service.getMessageAccessPermission(device); 1032 } 1033 setMessageAccessPermission(BluetoothDevice device, int value)1034 public boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1035 if (!Utils.checkCaller()) { 1036 Log.w(TAG, "setMessageAccessPermission() - Not allowed for non-active user"); 1037 return false; 1038 } 1039 1040 AdapterService service = getService(); 1041 if (service == null) return false; 1042 return service.setMessageAccessPermission(device, value); 1043 } 1044 sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)1045 public void sendConnectionStateChange(BluetoothDevice 1046 device, int profile, int state, int prevState) { 1047 AdapterService service = getService(); 1048 if (service == null) return; 1049 service.sendConnectionStateChange(device, profile, state, prevState); 1050 } 1051 connectSocket(BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag)1052 public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1053 ParcelUuid uuid, int port, int flag) { 1054 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1055 Log.w(TAG, "connectSocket() - Not allowed for non-active user"); 1056 return null; 1057 } 1058 1059 AdapterService service = getService(); 1060 if (service == null) return null; 1061 return service.connectSocket(device, type, uuid, port, flag); 1062 } 1063 createSocketChannel(int type, String serviceName, ParcelUuid uuid, int port, int flag)1064 public ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1065 ParcelUuid uuid, int port, int flag) { 1066 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 1067 Log.w(TAG, "createSocketChannel() - Not allowed for non-active user"); 1068 return null; 1069 } 1070 1071 AdapterService service = getService(); 1072 if (service == null) return null; 1073 return service.createSocketChannel(type, serviceName, uuid, port, flag); 1074 } 1075 configHciSnoopLog(boolean enable)1076 public boolean configHciSnoopLog(boolean enable) { 1077 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 1078 EventLog.writeEvent(0x534e4554 /* SNET */, "Bluetooth", Binder.getCallingUid(), 1079 "configHciSnoopLog() - Not allowed for non-active user b/18643224"); 1080 return false; 1081 } 1082 1083 AdapterService service = getService(); 1084 if (service == null) return false; 1085 return service.configHciSnoopLog(enable); 1086 } 1087 registerCallback(IBluetoothCallback cb)1088 public void registerCallback(IBluetoothCallback cb) { 1089 AdapterService service = getService(); 1090 if (service == null) return ; 1091 service.registerCallback(cb); 1092 } 1093 unregisterCallback(IBluetoothCallback cb)1094 public void unregisterCallback(IBluetoothCallback cb) { 1095 AdapterService service = getService(); 1096 if (service == null) return ; 1097 service.unregisterCallback(cb); 1098 } 1099 isMultiAdvertisementSupported()1100 public boolean isMultiAdvertisementSupported() { 1101 AdapterService service = getService(); 1102 if (service == null) return false; 1103 return service.isMultiAdvertisementSupported(); 1104 } 1105 isPeripheralModeSupported()1106 public boolean isPeripheralModeSupported() { 1107 AdapterService service = getService(); 1108 if (service == null) return false; 1109 return service.isPeripheralModeSupported(); 1110 } 1111 isOffloadedFilteringSupported()1112 public boolean isOffloadedFilteringSupported() { 1113 AdapterService service = getService(); 1114 if (service == null) return false; 1115 int val = service.getNumOfOffloadedScanFilterSupported(); 1116 return (val >= MIN_OFFLOADED_FILTERS); 1117 } 1118 isOffloadedScanBatchingSupported()1119 public boolean isOffloadedScanBatchingSupported() { 1120 AdapterService service = getService(); 1121 if (service == null) return false; 1122 int val = service.getOffloadedScanResultStorage(); 1123 return (val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES); 1124 } 1125 isActivityAndEnergyReportingSupported()1126 public boolean isActivityAndEnergyReportingSupported() { 1127 AdapterService service = getService(); 1128 if (service == null) return false; 1129 return service.isActivityAndEnergyReportingSupported(); 1130 } 1131 getActivityEnergyInfoFromController()1132 public void getActivityEnergyInfoFromController() { 1133 AdapterService service = getService(); 1134 if (service == null) return; 1135 service.getActivityEnergyInfoFromController(); 1136 } 1137 reportActivityInfo()1138 public BluetoothActivityEnergyInfo reportActivityInfo() { 1139 AdapterService service = getService(); 1140 if (service == null) return null; 1141 return service.reportActivityInfo(); 1142 } 1143 dump()1144 public String dump() { 1145 AdapterService service = getService(); 1146 if (service == null) { 1147 return "AdapterService is null"; 1148 } 1149 return service.dump(); 1150 } 1151 }; 1152 1153 1154 //----API Methods-------- isEnabled()1155 boolean isEnabled() { 1156 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1157 1158 return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON; 1159 } 1160 getState()1161 int getState() { 1162 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1163 1164 if (mAdapterProperties == null){ 1165 return BluetoothAdapter.STATE_OFF; 1166 } 1167 else { 1168 debugLog("getState() - mAdapterProperties: " + mAdapterProperties); 1169 return mAdapterProperties.getState(); 1170 } 1171 } 1172 enable()1173 boolean enable() { 1174 return enable (false); 1175 } 1176 enableNoAutoConnect()1177 public boolean enableNoAutoConnect() { 1178 return enable (true); 1179 } 1180 enable(boolean quietMode)1181 public synchronized boolean enable(boolean quietMode) { 1182 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1183 "Need BLUETOOTH ADMIN permission"); 1184 debugLog("enable() - Enable called with quiet mode status = " + mQuietmode); 1185 mQuietmode = quietMode; 1186 Message m = 1187 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON); 1188 mAdapterStateMachine.sendMessage(m); 1189 return true; 1190 } 1191 disable()1192 boolean disable() { 1193 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1194 "Need BLUETOOTH ADMIN permission"); 1195 1196 debugLog("disable() called..."); 1197 Message m = 1198 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF); 1199 mAdapterStateMachine.sendMessage(m); 1200 return true; 1201 } 1202 getAddress()1203 String getAddress() { 1204 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1205 1206 String addrString = null; 1207 byte[] address = mAdapterProperties.getAddress(); 1208 return Utils.getAddressStringFromByte(address); 1209 } 1210 getUuids()1211 ParcelUuid[] getUuids() { 1212 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1213 1214 return mAdapterProperties.getUuids(); 1215 } 1216 getName()1217 String getName() { 1218 enforceCallingOrSelfPermission(BLUETOOTH_PERM, 1219 "Need BLUETOOTH permission"); 1220 1221 try { 1222 return mAdapterProperties.getName(); 1223 } catch (Throwable t) { 1224 debugLog("getName() - Unexpected exception (" + t + ")"); 1225 } 1226 return null; 1227 } 1228 setName(String name)1229 boolean setName(String name) { 1230 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1231 "Need BLUETOOTH ADMIN permission"); 1232 1233 return mAdapterProperties.setName(name); 1234 } 1235 getScanMode()1236 int getScanMode() { 1237 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1238 1239 return mAdapterProperties.getScanMode(); 1240 } 1241 setScanMode(int mode, int duration)1242 boolean setScanMode(int mode, int duration) { 1243 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1244 1245 setDiscoverableTimeout(duration); 1246 1247 int newMode = convertScanModeToHal(mode); 1248 return mAdapterProperties.setScanMode(newMode); 1249 } 1250 getDiscoverableTimeout()1251 int getDiscoverableTimeout() { 1252 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1253 1254 return mAdapterProperties.getDiscoverableTimeout(); 1255 } 1256 setDiscoverableTimeout(int timeout)1257 boolean setDiscoverableTimeout(int timeout) { 1258 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1259 1260 return mAdapterProperties.setDiscoverableTimeout(timeout); 1261 } 1262 startDiscovery()1263 boolean startDiscovery() { 1264 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1265 "Need BLUETOOTH ADMIN permission"); 1266 1267 return startDiscoveryNative(); 1268 } 1269 cancelDiscovery()1270 boolean cancelDiscovery() { 1271 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1272 "Need BLUETOOTH ADMIN permission"); 1273 1274 return cancelDiscoveryNative(); 1275 } 1276 isDiscovering()1277 boolean isDiscovering() { 1278 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1279 1280 return mAdapterProperties.isDiscovering(); 1281 } 1282 getBondedDevices()1283 BluetoothDevice[] getBondedDevices() { 1284 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1285 return mAdapterProperties.getBondedDevices(); 1286 } 1287 getAdapterConnectionState()1288 int getAdapterConnectionState() { 1289 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1290 return mAdapterProperties.getConnectionState(); 1291 } 1292 getProfileConnectionState(int profile)1293 int getProfileConnectionState(int profile) { 1294 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1295 1296 return mAdapterProperties.getProfileConnectionState(profile); 1297 } 1298 createBond(BluetoothDevice device, int transport)1299 boolean createBond(BluetoothDevice device, int transport) { 1300 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1301 "Need BLUETOOTH ADMIN permission"); 1302 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1303 if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) { 1304 return false; 1305 } 1306 1307 // Pairing is unreliable while scanning, so cancel discovery 1308 // Note, remove this when native stack improves 1309 cancelDiscoveryNative(); 1310 1311 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND); 1312 msg.obj = device; 1313 msg.arg1 = transport; 1314 mBondStateMachine.sendMessage(msg); 1315 return true; 1316 } 1317 isQuietModeEnabled()1318 public boolean isQuietModeEnabled() { 1319 debugLog("isQuetModeEnabled() - Enabled = " + mQuietmode); 1320 return mQuietmode; 1321 } 1322 autoConnect()1323 public void autoConnect(){ 1324 if (getState() != BluetoothAdapter.STATE_ON){ 1325 errorLog("autoConnect() - BT is not ON. Exiting autoConnect"); 1326 return; 1327 } 1328 if (isQuietModeEnabled() == false) { 1329 debugLog( "autoConnect() - Initiate auto connection on BT on..."); 1330 autoConnectHeadset(); 1331 autoConnectA2dp(); 1332 } 1333 else { 1334 debugLog( "autoConnect() - BT is in quiet mode. Not initiating auto connections"); 1335 } 1336 } 1337 autoConnectHeadset()1338 private void autoConnectHeadset(){ 1339 HeadsetService hsService = HeadsetService.getHeadsetService(); 1340 1341 BluetoothDevice bondedDevices[] = getBondedDevices(); 1342 if ((bondedDevices == null) ||(hsService == null)) { 1343 return; 1344 } 1345 for (BluetoothDevice device : bondedDevices) { 1346 if (hsService.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1347 debugLog("autoConnectHeadset() - Connecting HFP with " + device.toString()); 1348 hsService.connect(device); 1349 } 1350 } 1351 } 1352 autoConnectA2dp()1353 private void autoConnectA2dp(){ 1354 A2dpService a2dpSservice = A2dpService.getA2dpService(); 1355 BluetoothDevice bondedDevices[] = getBondedDevices(); 1356 if ((bondedDevices == null) ||(a2dpSservice == null)) { 1357 return; 1358 } 1359 for (BluetoothDevice device : bondedDevices) { 1360 if (a2dpSservice.getPriority(device) == BluetoothProfile.PRIORITY_AUTO_CONNECT ){ 1361 debugLog("autoConnectA2dp() - Connecting A2DP with " + device.toString()); 1362 a2dpSservice.connect(device); 1363 } 1364 } 1365 } 1366 connectOtherProfile(BluetoothDevice device, int firstProfileStatus)1367 public void connectOtherProfile(BluetoothDevice device, int firstProfileStatus){ 1368 if ((mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES) == false) && 1369 (isQuietModeEnabled()== false)){ 1370 Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES); 1371 m.obj = device; 1372 m.arg1 = (int)firstProfileStatus; 1373 mHandler.sendMessageDelayed(m,CONNECT_OTHER_PROFILES_TIMEOUT); 1374 } 1375 } 1376 processConnectOtherProfiles(BluetoothDevice device, int firstProfileStatus)1377 private void processConnectOtherProfiles (BluetoothDevice device, int firstProfileStatus){ 1378 if (getState()!= BluetoothAdapter.STATE_ON){ 1379 return; 1380 } 1381 HeadsetService hsService = HeadsetService.getHeadsetService(); 1382 A2dpService a2dpService = A2dpService.getA2dpService(); 1383 1384 // if any of the profile service is null, second profile connection not required 1385 if ((hsService == null) ||(a2dpService == null )){ 1386 return; 1387 } 1388 List<BluetoothDevice> a2dpConnDevList= a2dpService.getConnectedDevices(); 1389 List<BluetoothDevice> hfConnDevList= hsService.getConnectedDevices(); 1390 // Check if the device is in disconnected state and if so return 1391 // We ned to connect other profile only if one of the profile is still in connected state 1392 // This is required to avoide a race condition in which profiles would 1393 // automaticlly connect if the disconnection is initiated within 6 seconds of connection 1394 //First profile connection being rejected is an exception 1395 if((hfConnDevList.isEmpty() && a2dpConnDevList.isEmpty())&& 1396 (PROFILE_CONN_CONNECTED == firstProfileStatus)){ 1397 return; 1398 } 1399 if((hfConnDevList.isEmpty()) && 1400 (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1401 hsService.connect(device); 1402 } 1403 else if((a2dpConnDevList.isEmpty()) && 1404 (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON)){ 1405 a2dpService.connect(device); 1406 } 1407 } 1408 adjustOtherHeadsetPriorities(HeadsetService hsService, List<BluetoothDevice> connectedDeviceList)1409 private void adjustOtherHeadsetPriorities(HeadsetService hsService, 1410 List<BluetoothDevice> connectedDeviceList) { 1411 for (BluetoothDevice device : getBondedDevices()) { 1412 if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1413 !connectedDeviceList.contains(device)) { 1414 hsService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1415 } 1416 } 1417 } 1418 adjustOtherSinkPriorities(A2dpService a2dpService, BluetoothDevice connectedDevice)1419 private void adjustOtherSinkPriorities(A2dpService a2dpService, 1420 BluetoothDevice connectedDevice) { 1421 for (BluetoothDevice device : getBondedDevices()) { 1422 if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && 1423 !device.equals(connectedDevice)) { 1424 a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); 1425 } 1426 } 1427 } 1428 setProfileAutoConnectionPriority(BluetoothDevice device, int profileId)1429 void setProfileAutoConnectionPriority (BluetoothDevice device, int profileId){ 1430 if (profileId == BluetoothProfile.HEADSET) { 1431 HeadsetService hsService = HeadsetService.getHeadsetService(); 1432 List<BluetoothDevice> deviceList = hsService.getConnectedDevices(); 1433 if ((hsService != null) && 1434 (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))){ 1435 adjustOtherHeadsetPriorities(hsService, deviceList); 1436 hsService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1437 } 1438 } 1439 else if (profileId == BluetoothProfile.A2DP) { 1440 A2dpService a2dpService = A2dpService.getA2dpService(); 1441 if ((a2dpService != null) && 1442 (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))){ 1443 adjustOtherSinkPriorities(a2dpService, device); 1444 a2dpService.setPriority(device,BluetoothProfile.PRIORITY_AUTO_CONNECT); 1445 } 1446 } 1447 } 1448 cancelBondProcess(BluetoothDevice device)1449 boolean cancelBondProcess(BluetoothDevice device) { 1450 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1451 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1452 return cancelBondNative(addr); 1453 } 1454 removeBond(BluetoothDevice device)1455 boolean removeBond(BluetoothDevice device) { 1456 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 1457 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1458 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { 1459 return false; 1460 } 1461 Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); 1462 msg.obj = device; 1463 mBondStateMachine.sendMessage(msg); 1464 return true; 1465 } 1466 getBondState(BluetoothDevice device)1467 int getBondState(BluetoothDevice device) { 1468 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1469 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1470 if (deviceProp == null) { 1471 return BluetoothDevice.BOND_NONE; 1472 } 1473 return deviceProp.getBondState(); 1474 } 1475 getConnectionState(BluetoothDevice device)1476 int getConnectionState(BluetoothDevice device) { 1477 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1478 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1479 return getConnectionStateNative(addr); 1480 } 1481 getRemoteName(BluetoothDevice device)1482 String getRemoteName(BluetoothDevice device) { 1483 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1484 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1485 if (deviceProp == null) return null; 1486 return deviceProp.getName(); 1487 } 1488 getRemoteType(BluetoothDevice device)1489 int getRemoteType(BluetoothDevice device) { 1490 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1491 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1492 if (deviceProp == null) return BluetoothDevice.DEVICE_TYPE_UNKNOWN; 1493 return deviceProp.getDeviceType(); 1494 } 1495 getRemoteAlias(BluetoothDevice device)1496 String getRemoteAlias(BluetoothDevice device) { 1497 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1498 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1499 if (deviceProp == null) return null; 1500 return deviceProp.getAlias(); 1501 } 1502 setRemoteAlias(BluetoothDevice device, String name)1503 boolean setRemoteAlias(BluetoothDevice device, String name) { 1504 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1505 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1506 if (deviceProp == null) return false; 1507 deviceProp.setAlias(name); 1508 return true; 1509 } 1510 getRemoteClass(BluetoothDevice device)1511 int getRemoteClass(BluetoothDevice device) { 1512 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1513 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1514 if (deviceProp == null) return 0; 1515 1516 return deviceProp.getBluetoothClass(); 1517 } 1518 getRemoteUuids(BluetoothDevice device)1519 ParcelUuid[] getRemoteUuids(BluetoothDevice device) { 1520 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1521 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1522 if (deviceProp == null) return null; 1523 return deviceProp.getUuids(); 1524 } 1525 fetchRemoteUuids(BluetoothDevice device)1526 boolean fetchRemoteUuids(BluetoothDevice device) { 1527 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1528 mRemoteDevices.fetchUuids(device); 1529 return true; 1530 } 1531 fetchRemoteMasInstances(BluetoothDevice device)1532 boolean fetchRemoteMasInstances(BluetoothDevice device) { 1533 enforceCallingOrSelfPermission(RECEIVE_MAP_PERM, "Need RECEIVE BLUETOOTH MAP permission"); 1534 mRemoteDevices.fetchMasInstances(device); 1535 return true; 1536 } 1537 setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode)1538 boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) { 1539 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1540 "Need BLUETOOTH ADMIN permission"); 1541 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1542 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1543 return false; 1544 } 1545 1546 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1547 return pinReplyNative(addr, accept, len, pinCode); 1548 } 1549 setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey)1550 boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) { 1551 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1552 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1553 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1554 return false; 1555 } 1556 1557 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1558 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept, 1559 Utils.byteArrayToInt(passkey)); 1560 } 1561 setPairingConfirmation(BluetoothDevice device, boolean accept)1562 boolean setPairingConfirmation(BluetoothDevice device, boolean accept) { 1563 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 1564 "Need BLUETOOTH ADMIN permission"); 1565 DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); 1566 if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) { 1567 return false; 1568 } 1569 1570 byte[] addr = Utils.getBytesFromAddress(device.getAddress()); 1571 return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, 1572 accept, 0); 1573 } 1574 getPhonebookAccessPermission(BluetoothDevice device)1575 int getPhonebookAccessPermission(BluetoothDevice device) { 1576 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1577 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1578 Context.MODE_PRIVATE); 1579 if (!pref.contains(device.getAddress())) { 1580 return BluetoothDevice.ACCESS_UNKNOWN; 1581 } 1582 return pref.getBoolean(device.getAddress(), false) 1583 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1584 } 1585 setPhonebookAccessPermission(BluetoothDevice device, int value)1586 boolean setPhonebookAccessPermission(BluetoothDevice device, int value) { 1587 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1588 "Need BLUETOOTH PRIVILEGED permission"); 1589 SharedPreferences pref = getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE, 1590 Context.MODE_PRIVATE); 1591 SharedPreferences.Editor editor = pref.edit(); 1592 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1593 editor.remove(device.getAddress()); 1594 } else { 1595 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1596 } 1597 return editor.commit(); 1598 } 1599 getMessageAccessPermission(BluetoothDevice device)1600 int getMessageAccessPermission(BluetoothDevice device) { 1601 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1602 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1603 Context.MODE_PRIVATE); 1604 if (!pref.contains(device.getAddress())) { 1605 return BluetoothDevice.ACCESS_UNKNOWN; 1606 } 1607 return pref.getBoolean(device.getAddress(), false) 1608 ? BluetoothDevice.ACCESS_ALLOWED : BluetoothDevice.ACCESS_REJECTED; 1609 } 1610 setMessageAccessPermission(BluetoothDevice device, int value)1611 boolean setMessageAccessPermission(BluetoothDevice device, int value) { 1612 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1613 "Need BLUETOOTH PRIVILEGED permission"); 1614 SharedPreferences pref = getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE, 1615 Context.MODE_PRIVATE); 1616 SharedPreferences.Editor editor = pref.edit(); 1617 if (value == BluetoothDevice.ACCESS_UNKNOWN) { 1618 editor.remove(device.getAddress()); 1619 } else { 1620 editor.putBoolean(device.getAddress(), value == BluetoothDevice.ACCESS_ALLOWED); 1621 } 1622 return editor.commit(); 1623 } 1624 sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState)1625 void sendConnectionStateChange(BluetoothDevice 1626 device, int profile, int state, int prevState) { 1627 // TODO(BT) permission check? 1628 // Since this is a binder call check if Bluetooth is on still 1629 if (getState() == BluetoothAdapter.STATE_OFF) return; 1630 1631 mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState); 1632 1633 } 1634 connectSocket(BluetoothDevice device, int type, ParcelUuid uuid, int port, int flag)1635 ParcelFileDescriptor connectSocket(BluetoothDevice device, int type, 1636 ParcelUuid uuid, int port, int flag) { 1637 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1638 int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()), 1639 type, Utils.uuidToByteArray(uuid), port, flag); 1640 if (fd < 0) { 1641 errorLog("Failed to connect socket"); 1642 return null; 1643 } 1644 return ParcelFileDescriptor.adoptFd(fd); 1645 } 1646 createSocketChannel(int type, String serviceName, ParcelUuid uuid, int port, int flag)1647 ParcelFileDescriptor createSocketChannel(int type, String serviceName, 1648 ParcelUuid uuid, int port, int flag) { 1649 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1650 int fd = createSocketChannelNative(type, serviceName, 1651 Utils.uuidToByteArray(uuid), port, flag); 1652 if (fd < 0) { 1653 errorLog("Failed to create socket channel"); 1654 return null; 1655 } 1656 return ParcelFileDescriptor.adoptFd(fd); 1657 } 1658 configHciSnoopLog(boolean enable)1659 boolean configHciSnoopLog(boolean enable) { 1660 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1661 return configHciSnoopLogNative(enable); 1662 } 1663 registerCallback(IBluetoothCallback cb)1664 void registerCallback(IBluetoothCallback cb) { 1665 mCallbacks.register(cb); 1666 } 1667 unregisterCallback(IBluetoothCallback cb)1668 void unregisterCallback(IBluetoothCallback cb) { 1669 mCallbacks.unregister(cb); 1670 } 1671 getNumOfAdvertisementInstancesSupported()1672 public int getNumOfAdvertisementInstancesSupported() { 1673 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1674 return mAdapterProperties.getNumOfAdvertisementInstancesSupported(); 1675 } 1676 isMultiAdvertisementSupported()1677 public boolean isMultiAdvertisementSupported() { 1678 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1679 return getNumOfAdvertisementInstancesSupported() >= MIN_ADVT_INSTANCES_FOR_MA; 1680 } 1681 isRpaOffloadSupported()1682 public boolean isRpaOffloadSupported() { 1683 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1684 return mAdapterProperties.isRpaOffloadSupported(); 1685 } 1686 getNumOfOffloadedIrkSupported()1687 public int getNumOfOffloadedIrkSupported() { 1688 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1689 return mAdapterProperties.getNumOfOffloadedIrkSupported(); 1690 } 1691 getNumOfOffloadedScanFilterSupported()1692 public int getNumOfOffloadedScanFilterSupported() { 1693 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1694 return mAdapterProperties.getNumOfOffloadedScanFilterSupported(); 1695 } 1696 isPeripheralModeSupported()1697 public boolean isPeripheralModeSupported() { 1698 return getResources().getBoolean(R.bool.config_bluetooth_le_peripheral_mode_supported); 1699 } 1700 getOffloadedScanResultStorage()1701 public int getOffloadedScanResultStorage() { 1702 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1703 return mAdapterProperties.getOffloadedScanResultStorage(); 1704 } 1705 isActivityAndEnergyReportingSupported()1706 private boolean isActivityAndEnergyReportingSupported() { 1707 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1708 return mAdapterProperties.isActivityAndEnergyReportingSupported(); 1709 } 1710 getActivityEnergyInfoFromController()1711 private void getActivityEnergyInfoFromController() { 1712 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1713 if (isActivityAndEnergyReportingSupported()) { 1714 readEnergyInfo(); 1715 } 1716 } 1717 reportActivityInfo()1718 private BluetoothActivityEnergyInfo reportActivityInfo() { 1719 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH permission"); 1720 BluetoothActivityEnergyInfo info = 1721 new BluetoothActivityEnergyInfo(mStackReportedState, mTxTimeTotalMs, 1722 mRxTimeTotalMs, mIdleTimeTotalMs, mEnergyUsedTotalVoltAmpSecMicro); 1723 // Read on clear values; a record of data is created with 1724 // timstamp and new samples are collected until read again 1725 mStackReportedState = 0; 1726 mTxTimeTotalMs = 0; 1727 mRxTimeTotalMs = 0; 1728 mIdleTimeTotalMs = 0; 1729 mEnergyUsedTotalVoltAmpSecMicro = 0; 1730 return info; 1731 } 1732 dump()1733 private String dump() { 1734 StringBuilder sb = new StringBuilder(); 1735 synchronized (mProfiles) { 1736 for (ProfileService profile : mProfiles) { 1737 profile.dump(sb); 1738 } 1739 } 1740 return sb.toString(); 1741 } 1742 convertScanModeToHal(int mode)1743 private static int convertScanModeToHal(int mode) { 1744 switch (mode) { 1745 case BluetoothAdapter.SCAN_MODE_NONE: 1746 return AbstractionLayer.BT_SCAN_MODE_NONE; 1747 case BluetoothAdapter.SCAN_MODE_CONNECTABLE: 1748 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE; 1749 case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1750 return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1751 } 1752 // errorLog("Incorrect scan mode in convertScanModeToHal"); 1753 return -1; 1754 } 1755 convertScanModeFromHal(int mode)1756 static int convertScanModeFromHal(int mode) { 1757 switch (mode) { 1758 case AbstractionLayer.BT_SCAN_MODE_NONE: 1759 return BluetoothAdapter.SCAN_MODE_NONE; 1760 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE: 1761 return BluetoothAdapter.SCAN_MODE_CONNECTABLE; 1762 case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE: 1763 return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; 1764 } 1765 //errorLog("Incorrect scan mode in convertScanModeFromHal"); 1766 return -1; 1767 } 1768 1769 // This function is called from JNI. It allows native code to set a single wake 1770 // alarm. setWakeAlarm(long delayMillis, boolean shouldWake)1771 private boolean setWakeAlarm(long delayMillis, boolean shouldWake) { 1772 Message m = mHandler.obtainMessage(MESSAGE_SET_WAKE_ALARM); 1773 m.obj = new Long(delayMillis); 1774 // alarm type 1775 m.arg1 = shouldWake ? AlarmManager.ELAPSED_REALTIME_WAKEUP 1776 : AlarmManager.ELAPSED_REALTIME; 1777 mHandler.sendMessage(m); 1778 1779 return true; 1780 } 1781 1782 // If an alarm is already pending and a new request comes in, the alarm 1783 // will be rescheduled (i.e. the previously set alarm will be cancelled). processSetWakeAlarm(long delayMillis, int alarmType)1784 private void processSetWakeAlarm(long delayMillis, int alarmType) { 1785 if (mPendingAlarm != null) { 1786 mAlarmManager.cancel(mPendingAlarm); 1787 } 1788 1789 long wakeupTime = SystemClock.elapsedRealtime() + delayMillis; 1790 1791 Intent intent = new Intent(ACTION_ALARM_WAKEUP); 1792 mPendingAlarm = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); 1793 mAlarmManager.setExact(alarmType, wakeupTime, mPendingAlarm); 1794 } 1795 1796 // This function is called from JNI. It allows native code to acquire a single wake lock. 1797 // If the wake lock is already held, this function returns success. Although this function 1798 // only supports acquiring a single wake lock at a time right now, it will eventually be 1799 // extended to allow acquiring an arbitrary number of wake locks. The current interface 1800 // takes |lockName| as a parameter in anticipation of that implementation. acquireWakeLock(String lockName)1801 private boolean acquireWakeLock(String lockName) { 1802 if (mWakeLock != null) { 1803 if (!lockName.equals(mWakeLockName)) { 1804 errorLog("Multiple wake lock acquisition attempted; aborting: " + lockName); 1805 return false; 1806 } 1807 1808 // We're already holding the desired wake lock so return success. 1809 if (mWakeLock.isHeld()) { 1810 return true; 1811 } 1812 } 1813 1814 mWakeLockName = lockName; 1815 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, lockName); 1816 mWakeLock.acquire(); 1817 return true; 1818 } 1819 1820 // This function is called from JNI. It allows native code to release a wake lock acquired 1821 // by |acquireWakeLock|. If the wake lock is not held, this function returns failure. 1822 // Note that the release() call is also invoked by {@link #cleanup()} so a synchronization is 1823 // needed here. See the comment for |acquireWakeLock| for an explanation of the interface. releaseWakeLock(String lockName)1824 private boolean releaseWakeLock(String lockName) { 1825 synchronized (this) { 1826 if (mWakeLock == null) { 1827 errorLog("Repeated wake lock release; aborting release: " + lockName); 1828 return false; 1829 } 1830 1831 mWakeLock.release(); 1832 mWakeLock = null; 1833 mWakeLockName = null; 1834 } 1835 return true; 1836 } 1837 energyInfoCallback(int status, int ctrl_state, long tx_time, long rx_time, long idle_time, long energy_used)1838 private void energyInfoCallback (int status, int ctrl_state, 1839 long tx_time, long rx_time, long idle_time, long energy_used) 1840 throws RemoteException { 1841 // ToDo: Update only status is valid 1842 if (ctrl_state >= BluetoothActivityEnergyInfo.BT_STACK_STATE_INVALID && 1843 ctrl_state <= BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_IDLE) { 1844 mStackReportedState = ctrl_state; 1845 mTxTimeTotalMs += tx_time; 1846 mRxTimeTotalMs += rx_time; 1847 mIdleTimeTotalMs += idle_time; 1848 // Energy is product of mA, V and ms 1849 mEnergyUsedTotalVoltAmpSecMicro += energy_used; 1850 } 1851 1852 if (DBG) { 1853 Log.d(TAG, "energyInfoCallback " + "status = " + status + 1854 "tx_time = " + tx_time + "rx_time = " + rx_time + 1855 "idle_time = " + idle_time + "energy_used = " + energy_used + 1856 "ctrl_state = " + ctrl_state); 1857 } 1858 } 1859 debugLog(String msg)1860 private void debugLog(String msg) { 1861 if (DBG) Log.d(TAG +"(" +hashCode()+")", msg); 1862 } 1863 errorLog(String msg)1864 private void errorLog(String msg) { 1865 Log.e(TAG +"(" +hashCode()+")", msg); 1866 } 1867 1868 private final BroadcastReceiver mAlarmBroadcastReceiver = new BroadcastReceiver() { 1869 @Override 1870 public void onReceive(Context context, Intent intent) { 1871 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_RELEASE_WAKE_ALARM)); 1872 } 1873 }; 1874 classInitNative()1875 private native static void classInitNative(); initNative()1876 private native boolean initNative(); cleanupNative()1877 private native void cleanupNative(); enableNative()1878 /*package*/ native boolean enableNative(); disableNative()1879 /*package*/ native boolean disableNative(); setAdapterPropertyNative(int type, byte[] val)1880 /*package*/ native boolean setAdapterPropertyNative(int type, byte[] val); getAdapterPropertiesNative()1881 /*package*/ native boolean getAdapterPropertiesNative(); getAdapterPropertyNative(int type)1882 /*package*/ native boolean getAdapterPropertyNative(int type); setAdapterPropertyNative(int type)1883 /*package*/ native boolean setAdapterPropertyNative(int type); 1884 /*package*/ native boolean setDevicePropertyNative(byte[] address, int type, byte[] val)1885 setDevicePropertyNative(byte[] address, int type, byte[] val); getDevicePropertyNative(byte[] address, int type)1886 /*package*/ native boolean getDevicePropertyNative(byte[] address, int type); 1887 createBondNative(byte[] address, int transport)1888 /*package*/ native boolean createBondNative(byte[] address, int transport); removeBondNative(byte[] address)1889 /*package*/ native boolean removeBondNative(byte[] address); cancelBondNative(byte[] address)1890 /*package*/ native boolean cancelBondNative(byte[] address); 1891 getConnectionStateNative(byte[] address)1892 /*package*/ native int getConnectionStateNative(byte[] address); 1893 startDiscoveryNative()1894 private native boolean startDiscoveryNative(); cancelDiscoveryNative()1895 private native boolean cancelDiscoveryNative(); 1896 pinReplyNative(byte[] address, boolean accept, int len, byte[] pin)1897 private native boolean pinReplyNative(byte[] address, boolean accept, int len, byte[] pin); sspReplyNative(byte[] address, int type, boolean accept, int passkey)1898 private native boolean sspReplyNative(byte[] address, int type, boolean 1899 accept, int passkey); 1900 getRemoteServicesNative(byte[] address)1901 /*package*/ native boolean getRemoteServicesNative(byte[] address); getRemoteMasInstancesNative(byte[] address)1902 /*package*/ native boolean getRemoteMasInstancesNative(byte[] address); 1903 readEnergyInfo()1904 private native int readEnergyInfo(); 1905 // TODO(BT) move this to ../btsock dir connectSocketNative(byte[] address, int type, byte[] uuid, int port, int flag)1906 private native int connectSocketNative(byte[] address, int type, 1907 byte[] uuid, int port, int flag); createSocketChannelNative(int type, String serviceName, byte[] uuid, int port, int flag)1908 private native int createSocketChannelNative(int type, String serviceName, 1909 byte[] uuid, int port, int flag); 1910 configHciSnoopLogNative(boolean enable)1911 /*package*/ native boolean configHciSnoopLogNative(boolean enable); 1912 alarmFiredNative()1913 private native void alarmFiredNative(); 1914 finalize()1915 protected void finalize() { 1916 cleanup(); 1917 if (TRACE_REF) { 1918 synchronized (AdapterService.class) { 1919 sRefCount--; 1920 debugLog("finalize() - REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount); 1921 } 1922 } 1923 } 1924 } 1925