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