BluetoothManagerService.java revision a0eaaa2a22def29a0c3cb9645a105b773048f5ee
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import android.app.ActivityManager; 20import android.bluetooth.BluetoothAdapter; 21import android.bluetooth.BluetoothProfile; 22import android.bluetooth.IBluetooth; 23import android.bluetooth.IBluetoothGatt; 24import android.bluetooth.IBluetoothCallback; 25import android.bluetooth.IBluetoothHeadset; 26import android.bluetooth.IBluetoothManager; 27import android.bluetooth.IBluetoothManagerCallback; 28import android.bluetooth.IBluetoothProfileServiceConnection; 29import android.bluetooth.IBluetoothStateChangeCallback; 30import android.content.BroadcastReceiver; 31import android.content.ComponentName; 32import android.content.ContentResolver; 33import android.content.Context; 34import android.content.Intent; 35import android.content.IntentFilter; 36import android.content.ServiceConnection; 37import android.content.pm.PackageManager; 38import android.content.pm.UserInfo; 39import android.os.Binder; 40import android.os.Handler; 41import android.os.IBinder; 42import android.os.Looper; 43import android.os.Message; 44import android.os.ParcelFileDescriptor; 45import android.os.Process; 46import android.os.RemoteCallbackList; 47import android.os.RemoteException; 48import android.os.SystemClock; 49import android.os.UserHandle; 50import android.os.UserManager; 51import android.provider.Settings; 52import android.util.Log; 53 54import java.io.FileDescriptor; 55import java.io.IOException; 56import java.io.PrintWriter; 57 58import java.util.HashMap; 59import java.util.Map; 60import java.util.List; 61import java.util.Vector; 62 63class BluetoothManagerService extends IBluetoothManager.Stub { 64 private static final String TAG = "BluetoothManagerService"; 65 private static final boolean DBG = true; 66 67 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 68 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 69 private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 70 private static final String EXTRA_ACTION="action"; 71 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; 72 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 73 private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 74 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 75 private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 76 //Maximum msec to wait for service restart 77 private static final int SERVICE_RESTART_TIME_MS = 200; 78 //Maximum msec to wait for restart due to error 79 private static final int ERROR_RESTART_TIME_MS = 3000; 80 //Maximum msec to delay MESSAGE_USER_SWITCHED 81 private static final int USER_SWITCHED_TIME_MS = 200; 82 // Delay for the addProxy function in msec 83 private static final int ADD_PROXY_DELAY_MS = 100; 84 85 private static final int MESSAGE_ENABLE = 1; 86 private static final int MESSAGE_DISABLE = 2; 87 private static final int MESSAGE_REGISTER_ADAPTER = 20; 88 private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 89 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 90 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 91 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 92 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 93 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 94 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60; 95 private static final int MESSAGE_TIMEOUT_BIND =100; 96 private static final int MESSAGE_TIMEOUT_UNBIND =101; 97 private static final int MESSAGE_GET_NAME_AND_ADDRESS=200; 98 private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201; 99 private static final int MESSAGE_USER_SWITCHED = 300; 100 private static final int MESSAGE_ADD_PROXY_DELAYED = 400; 101 private static final int MESSAGE_BIND_PROFILE_SERVICE = 401; 102 private static final int MAX_SAVE_RETRIES=3; 103 private static final int MAX_ERROR_RESTART_RETRIES=6; 104 105 // Bluetooth persisted setting is off 106 private static final int BLUETOOTH_OFF=0; 107 // Bluetooth persisted setting is on 108 // and Airplane mode won't affect Bluetooth state at start up 109 private static final int BLUETOOTH_ON_BLUETOOTH=1; 110 // Bluetooth persisted setting is on 111 // but Airplane mode will affect Bluetooth state at start up 112 // and Airplane mode will have higher priority. 113 private static final int BLUETOOTH_ON_AIRPLANE=2; 114 115 private static final int SERVICE_IBLUETOOTH = 1; 116 private static final int SERVICE_IBLUETOOTHGATT = 2; 117 118 private final Context mContext; 119 120 // Locks are not provided for mName and mAddress. 121 // They are accessed in handler or broadcast receiver, same thread context. 122 private String mAddress; 123 private String mName; 124 private final ContentResolver mContentResolver; 125 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 126 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 127 private IBluetooth mBluetooth; 128 private IBluetoothGatt mBluetoothGatt; 129 private boolean mBinding; 130 private boolean mUnbinding; 131 // used inside handler thread 132 private boolean mQuietEnable = false; 133 // configuarion from external IBinder call which is used to 134 // synchronize with broadcast receiver. 135 private boolean mQuietEnableExternal; 136 // configuarion from external IBinder call which is used to 137 // synchronize with broadcast receiver. 138 private boolean mEnableExternal; 139 // used inside handler thread 140 private boolean mEnable; 141 private int mState; 142 private final BluetoothHandler mHandler; 143 private int mErrorRecoveryRetryCounter; 144 private final int mSystemUiUid; 145 146 // Save a ProfileServiceConnections object for each of the bound 147 // bluetooth profile services 148 private final Map <Integer, ProfileServiceConnections> mProfileServices = 149 new HashMap <Integer, ProfileServiceConnections>(); 150 151 private void registerForAirplaneMode(IntentFilter filter) { 152 final ContentResolver resolver = mContext.getContentResolver(); 153 final String airplaneModeRadios = Settings.Global.getString(resolver, 154 Settings.Global.AIRPLANE_MODE_RADIOS); 155 final String toggleableRadios = Settings.Global.getString(resolver, 156 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 157 boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 158 airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); 159 if (mIsAirplaneSensitive) { 160 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 161 } 162 } 163 164 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 165 @Override 166 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 167 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); 168 mHandler.sendMessage(msg); 169 } 170 }; 171 172 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 173 @Override 174 public void onReceive(Context context, Intent intent) { 175 String action = intent.getAction(); 176 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 177 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 178 if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName); 179 if (newName != null) { 180 storeNameAndAddress(newName, null); 181 } 182 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 183 synchronized(mReceiver) { 184 if (isBluetoothPersistedStateOn()) { 185 if (isAirplaneModeOn()) { 186 persistBluetoothSetting(BLUETOOTH_ON_AIRPLANE); 187 } else { 188 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 189 } 190 } 191 if (isAirplaneModeOn()) { 192 // disable without persisting the setting 193 sendDisableMsg(); 194 } else if (mEnableExternal) { 195 // enable without persisting the setting 196 sendEnableMsg(mQuietEnableExternal); 197 } 198 } 199 } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { 200 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, 201 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); 202 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 203 synchronized(mReceiver) { 204 if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { 205 //Enable 206 if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); 207 sendEnableMsg(mQuietEnableExternal); 208 } 209 } 210 211 if (!isNameAndAddressSet()) { 212 //Sync the Bluetooth name and address from the Bluetooth Adapter 213 if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); 214 getNameAndAddress(); 215 } 216 } 217 } 218 }; 219 220 BluetoothManagerService(Context context) { 221 mHandler = new BluetoothHandler(IoThread.get().getLooper()); 222 223 mContext = context; 224 mBluetooth = null; 225 mBinding = false; 226 mUnbinding = false; 227 mEnable = false; 228 mState = BluetoothAdapter.STATE_OFF; 229 mQuietEnableExternal = false; 230 mEnableExternal = false; 231 mAddress = null; 232 mName = null; 233 mErrorRecoveryRetryCounter = 0; 234 mContentResolver = context.getContentResolver(); 235 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 236 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 237 IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); 238 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 239 filter.addAction(Intent.ACTION_USER_SWITCHED); 240 registerForAirplaneMode(filter); 241 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 242 mContext.registerReceiver(mReceiver, filter); 243 loadStoredNameAndAddress(); 244 if (isBluetoothPersistedStateOn()) { 245 mEnableExternal = true; 246 } 247 248 int sysUiUid = -1; 249 try { 250 sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", 251 UserHandle.USER_OWNER); 252 } catch (PackageManager.NameNotFoundException e) { 253 Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e); 254 } 255 mSystemUiUid = sysUiUid; 256 } 257 258 /** 259 * Returns true if airplane mode is currently on 260 */ 261 private final boolean isAirplaneModeOn() { 262 return Settings.Global.getInt(mContext.getContentResolver(), 263 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 264 } 265 266 /** 267 * Returns true if the Bluetooth saved state is "on" 268 */ 269 private final boolean isBluetoothPersistedStateOn() { 270 return Settings.Global.getInt(mContentResolver, 271 Settings.Global.BLUETOOTH_ON, 0) != BLUETOOTH_OFF; 272 } 273 274 /** 275 * Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH 276 */ 277 private final boolean isBluetoothPersistedStateOnBluetooth() { 278 return Settings.Global.getInt(mContentResolver, 279 Settings.Global.BLUETOOTH_ON, 0) == BLUETOOTH_ON_BLUETOOTH; 280 } 281 282 /** 283 * Save the Bluetooth on/off state 284 * 285 */ 286 private void persistBluetoothSetting(int value) { 287 Settings.Global.putInt(mContext.getContentResolver(), 288 Settings.Global.BLUETOOTH_ON, 289 value); 290 } 291 292 /** 293 * Returns true if the Bluetooth Adapter's name and address is 294 * locally cached 295 * @return 296 */ 297 private boolean isNameAndAddressSet() { 298 return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 299 } 300 301 /** 302 * Retrieve the Bluetooth Adapter's name and address and save it in 303 * in the local cache 304 */ 305 private void loadStoredNameAndAddress() { 306 if (DBG) Log.d(TAG, "Loading stored name and address"); 307 if (mContext.getResources().getBoolean 308 (com.android.internal.R.bool.config_bluetooth_address_validation) && 309 Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { 310 // if the valid flag is not set, don't load the address and name 311 if (DBG) Log.d(TAG, "invalid bluetooth name and address stored"); 312 return; 313 } 314 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 315 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 316 if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 317 } 318 319 /** 320 * Save the Bluetooth name and address in the persistent store. 321 * Only non-null values will be saved. 322 * @param name 323 * @param address 324 */ 325 private void storeNameAndAddress(String name, String address) { 326 if (name != null) { 327 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 328 mName = name; 329 if (DBG) Log.d(TAG,"Stored Bluetooth name: " + 330 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 331 } 332 333 if (address != null) { 334 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 335 mAddress=address; 336 if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " + 337 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 338 } 339 340 if ((name != null) && (address != null)) { 341 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 342 } 343 } 344 345 public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 346 if (callback == null) { 347 Log.w(TAG, "Callback is null in registerAdapter"); 348 return null; 349 } 350 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 351 msg.obj = callback; 352 mHandler.sendMessage(msg); 353 synchronized(mConnection) { 354 return mBluetooth; 355 } 356 } 357 358 public void unregisterAdapter(IBluetoothManagerCallback callback) { 359 if (callback == null) { 360 Log.w(TAG, "Callback is null in unregisterAdapter"); 361 return; 362 } 363 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 364 "Need BLUETOOTH permission"); 365 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 366 msg.obj = callback; 367 mHandler.sendMessage(msg); 368 } 369 370 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 371 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 372 "Need BLUETOOTH permission"); 373 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 374 msg.obj = callback; 375 mHandler.sendMessage(msg); 376 } 377 378 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 379 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 380 "Need BLUETOOTH permission"); 381 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 382 msg.obj = callback; 383 mHandler.sendMessage(msg); 384 } 385 386 public boolean isEnabled() { 387 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 388 (!checkIfCallerIsForegroundUser())) { 389 Log.w(TAG,"isEnabled(): not allowed for non-active and non system user"); 390 return false; 391 } 392 393 synchronized(mConnection) { 394 try { 395 return (mBluetooth != null && mBluetooth.isEnabled()); 396 } catch (RemoteException e) { 397 Log.e(TAG, "isEnabled()", e); 398 } 399 } 400 return false; 401 } 402 403 public void getNameAndAddress() { 404 if (DBG) { 405 Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth + 406 " mBinding = " + mBinding); 407 } 408 Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 409 mHandler.sendMessage(msg); 410 } 411 public boolean enableNoAutoConnect() 412 { 413 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 414 "Need BLUETOOTH ADMIN permission"); 415 416 if (DBG) { 417 Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 418 " mBinding = " + mBinding); 419 } 420 int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); 421 422 if (callingAppId != Process.NFC_UID) { 423 throw new SecurityException("no permission to enable Bluetooth quietly"); 424 } 425 426 synchronized(mReceiver) { 427 mQuietEnableExternal = true; 428 mEnableExternal = true; 429 sendEnableMsg(true); 430 } 431 return true; 432 433 } 434 public boolean enable() { 435 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 436 (!checkIfCallerIsForegroundUser())) { 437 Log.w(TAG,"enable(): not allowed for non-active and non system user"); 438 return false; 439 } 440 441 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 442 "Need BLUETOOTH ADMIN permission"); 443 if (DBG) { 444 Log.d(TAG,"enable(): mBluetooth =" + mBluetooth + 445 " mBinding = " + mBinding); 446 } 447 448 synchronized(mReceiver) { 449 mQuietEnableExternal = false; 450 mEnableExternal = true; 451 // waive WRITE_SECURE_SETTINGS permission check 452 long callingIdentity = Binder.clearCallingIdentity(); 453 persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); 454 Binder.restoreCallingIdentity(callingIdentity); 455 sendEnableMsg(false); 456 } 457 return true; 458 } 459 460 public boolean disable(boolean persist) { 461 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 462 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 463 464 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 465 (!checkIfCallerIsForegroundUser())) { 466 Log.w(TAG,"disable(): not allowed for non-active and non system user"); 467 return false; 468 } 469 470 if (DBG) { 471 Log.d(TAG,"disable(): mBluetooth = " + mBluetooth + 472 " mBinding = " + mBinding); 473 } 474 475 synchronized(mReceiver) { 476 if (persist) { 477 // waive WRITE_SECURE_SETTINGS permission check 478 long callingIdentity = Binder.clearCallingIdentity(); 479 persistBluetoothSetting(BLUETOOTH_OFF); 480 Binder.restoreCallingIdentity(callingIdentity); 481 } 482 mEnableExternal = false; 483 sendDisableMsg(); 484 } 485 return true; 486 } 487 488 public void unbindAndFinish() { 489 if (DBG) { 490 Log.d(TAG,"unbindAndFinish(): " + mBluetooth + 491 " mBinding = " + mBinding); 492 } 493 494 synchronized (mConnection) { 495 if (mUnbinding) return; 496 mUnbinding = true; 497 if (mBluetooth != null) { 498 if (!mConnection.isGetNameAddressOnly()) { 499 //Unregister callback object 500 try { 501 mBluetooth.unregisterCallback(mBluetoothCallback); 502 } catch (RemoteException re) { 503 Log.e(TAG, "Unable to unregister BluetoothCallback",re); 504 } 505 } 506 if (DBG) Log.d(TAG, "Sending unbind request."); 507 mBluetooth = null; 508 //Unbind 509 mContext.unbindService(mConnection); 510 mUnbinding = false; 511 mBinding = false; 512 } else { 513 mUnbinding=false; 514 } 515 } 516 } 517 518 public IBluetoothGatt getBluetoothGatt() { 519 // sync protection 520 return mBluetoothGatt; 521 } 522 523 @Override 524 public boolean bindBluetoothProfileService(int bluetoothProfile, 525 IBluetoothProfileServiceConnection proxy) { 526 if (!mEnable) { 527 if (DBG) { 528 Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile + 529 ", while Bluetooth was disabled"); 530 } 531 return false; 532 } 533 synchronized (mProfileServices) { 534 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 535 if (psc == null) { 536 if (DBG) { 537 Log.d(TAG, "Creating new ProfileServiceConnections object for" 538 + " profile: " + bluetoothProfile); 539 } 540 541 if (bluetoothProfile != BluetoothProfile.HEADSET) return false; 542 543 Intent intent = new Intent(IBluetoothHeadset.class.getName()); 544 psc = new ProfileServiceConnections(intent); 545 if (!psc.bindService()) return false; 546 547 mProfileServices.put(new Integer(bluetoothProfile), psc); 548 } 549 } 550 551 // Introducing a delay to give the client app time to prepare 552 Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED); 553 addProxyMsg.arg1 = bluetoothProfile; 554 addProxyMsg.obj = proxy; 555 mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS); 556 return true; 557 } 558 559 @Override 560 public void unbindBluetoothProfileService(int bluetoothProfile, 561 IBluetoothProfileServiceConnection proxy) { 562 synchronized (mProfileServices) { 563 ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); 564 if (psc == null) { 565 return; 566 } 567 psc.removeProxy(proxy); 568 } 569 } 570 571 private void unbindAllBluetoothProfileServices() { 572 synchronized (mProfileServices) { 573 for (Integer i : mProfileServices.keySet()) { 574 ProfileServiceConnections psc = mProfileServices.get(i); 575 try { 576 mContext.unbindService(psc); 577 } catch (IllegalArgumentException e) { 578 Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); 579 } 580 psc.removeAllProxies(); 581 } 582 mProfileServices.clear(); 583 } 584 } 585 586 /** 587 * This class manages the clients connected to a given ProfileService 588 * and maintains the connection with that service. 589 */ 590 final private class ProfileServiceConnections implements ServiceConnection, 591 IBinder.DeathRecipient { 592 final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies = 593 new RemoteCallbackList <IBluetoothProfileServiceConnection>(); 594 IBinder mService; 595 ComponentName mClassName; 596 Intent mIntent; 597 598 ProfileServiceConnections(Intent intent) { 599 mService = null; 600 mClassName = null; 601 mIntent = intent; 602 } 603 604 private boolean bindService() { 605 if (mIntent != null && mService == null && 606 doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { 607 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 608 msg.obj = this; 609 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 610 return true; 611 } 612 Log.w(TAG, "Unable to bind with intent: " + mIntent); 613 return false; 614 } 615 616 private void addProxy(IBluetoothProfileServiceConnection proxy) { 617 mProxies.register(proxy); 618 if (mService != null) { 619 try{ 620 proxy.onServiceConnected(mClassName, mService); 621 } catch (RemoteException e) { 622 Log.e(TAG, "Unable to connect to proxy", e); 623 } 624 } else { 625 if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { 626 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 627 msg.obj = this; 628 mHandler.sendMessage(msg); 629 } 630 } 631 } 632 633 private void removeProxy(IBluetoothProfileServiceConnection proxy) { 634 if (proxy != null) { 635 if (mProxies.unregister(proxy)) { 636 try { 637 proxy.onServiceDisconnected(mClassName); 638 } catch (RemoteException e) { 639 Log.e(TAG, "Unable to disconnect proxy", e); 640 } 641 } 642 } else { 643 Log.w(TAG, "Trying to remove a null proxy"); 644 } 645 } 646 647 private void removeAllProxies() { 648 onServiceDisconnected(mClassName); 649 mProxies.kill(); 650 } 651 652 @Override 653 public void onServiceConnected(ComponentName className, IBinder service) { 654 // remove timeout message 655 mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this); 656 mService = service; 657 mClassName = className; 658 try { 659 mService.linkToDeath(this, 0); 660 } catch (RemoteException e) { 661 Log.e(TAG, "Unable to linkToDeath", e); 662 } 663 int n = mProxies.beginBroadcast(); 664 for (int i = 0; i < n; i++) { 665 try { 666 mProxies.getBroadcastItem(i).onServiceConnected(className, service); 667 } catch (RemoteException e) { 668 Log.e(TAG, "Unable to connect to proxy", e); 669 } 670 } 671 mProxies.finishBroadcast(); 672 } 673 674 @Override 675 public void onServiceDisconnected(ComponentName className) { 676 if (mService == null) { 677 return; 678 } 679 mService.unlinkToDeath(this, 0); 680 mService = null; 681 mClassName = null; 682 int n = mProxies.beginBroadcast(); 683 for (int i = 0; i < n; i++) { 684 try { 685 mProxies.getBroadcastItem(i).onServiceDisconnected(className); 686 } catch (RemoteException e) { 687 Log.e(TAG, "Unable to disconnect from proxy", e); 688 } 689 } 690 mProxies.finishBroadcast(); 691 } 692 693 @Override 694 public void binderDied() { 695 if (DBG) { 696 Log.w(TAG, "Profile service for profile: " + mClassName 697 + " died."); 698 } 699 onServiceDisconnected(mClassName); 700 // Trigger rebind 701 Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); 702 msg.obj = this; 703 mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); 704 } 705 } 706 707 private void sendBluetoothStateCallback(boolean isUp) { 708 int n = mStateChangeCallbacks.beginBroadcast(); 709 if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 710 for (int i=0; i <n;i++) { 711 try { 712 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 713 } catch (RemoteException e) { 714 Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 715 } 716 } 717 mStateChangeCallbacks.finishBroadcast(); 718 } 719 720 /** 721 * Inform BluetoothAdapter instances that Adapter service is up 722 */ 723 private void sendBluetoothServiceUpCallback() { 724 if (!mConnection.isGetNameAddressOnly()) { 725 if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks"); 726 int n = mCallbacks.beginBroadcast(); 727 Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 728 for (int i=0; i <n;i++) { 729 try { 730 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 731 } catch (RemoteException e) { 732 Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 733 } 734 } 735 mCallbacks.finishBroadcast(); 736 } 737 } 738 /** 739 * Inform BluetoothAdapter instances that Adapter service is down 740 */ 741 private void sendBluetoothServiceDownCallback() { 742 if (!mConnection.isGetNameAddressOnly()) { 743 if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks"); 744 int n = mCallbacks.beginBroadcast(); 745 Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 746 for (int i=0; i <n;i++) { 747 try { 748 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 749 } catch (RemoteException e) { 750 Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 751 } 752 } 753 mCallbacks.finishBroadcast(); 754 } 755 } 756 public String getAddress() { 757 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 758 "Need BLUETOOTH permission"); 759 760 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 761 (!checkIfCallerIsForegroundUser())) { 762 Log.w(TAG,"getAddress(): not allowed for non-active and non system user"); 763 return null; 764 } 765 766 synchronized(mConnection) { 767 if (mBluetooth != null) { 768 try { 769 return mBluetooth.getAddress(); 770 } catch (RemoteException e) { 771 Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e); 772 } 773 } 774 } 775 // mAddress is accessed from outside. 776 // It is alright without a lock. Here, bluetooth is off, no other thread is 777 // changing mAddress 778 return mAddress; 779 } 780 781 public String getName() { 782 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 783 "Need BLUETOOTH permission"); 784 785 if ((Binder.getCallingUid() != Process.SYSTEM_UID) && 786 (!checkIfCallerIsForegroundUser())) { 787 Log.w(TAG,"getName(): not allowed for non-active and non system user"); 788 return null; 789 } 790 791 synchronized(mConnection) { 792 if (mBluetooth != null) { 793 try { 794 return mBluetooth.getName(); 795 } catch (RemoteException e) { 796 Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e); 797 } 798 } 799 } 800 // mName is accessed from outside. 801 // It alright without a lock. Here, bluetooth is off, no other thread is 802 // changing mName 803 return mName; 804 } 805 806 private class BluetoothServiceConnection implements ServiceConnection { 807 808 private boolean mGetNameAddressOnly; 809 810 public void setGetNameAddressOnly(boolean getOnly) { 811 mGetNameAddressOnly = getOnly; 812 } 813 814 public boolean isGetNameAddressOnly() { 815 return mGetNameAddressOnly; 816 } 817 818 public void onServiceConnected(ComponentName className, IBinder service) { 819 if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName()); 820 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 821 // TBD if (className.getClassName().equals(IBluetooth.class.getName())) { 822 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 823 msg.arg1 = SERVICE_IBLUETOOTH; 824 // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) { 825 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 826 msg.arg1 = SERVICE_IBLUETOOTHGATT; 827 } else { 828 Log.e(TAG, "Unknown service connected: " + className.getClassName()); 829 return; 830 } 831 msg.obj = service; 832 mHandler.sendMessage(msg); 833 } 834 835 public void onServiceDisconnected(ComponentName className) { 836 // Called if we unexpected disconnected. 837 if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " + 838 className.getClassName()); 839 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 840 if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) { 841 msg.arg1 = SERVICE_IBLUETOOTH; 842 } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) { 843 msg.arg1 = SERVICE_IBLUETOOTHGATT; 844 } else { 845 Log.e(TAG, "Unknown service disconnected: " + className.getClassName()); 846 return; 847 } 848 mHandler.sendMessage(msg); 849 } 850 } 851 852 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 853 854 private class BluetoothHandler extends Handler { 855 public BluetoothHandler(Looper looper) { 856 super(looper); 857 } 858 859 @Override 860 public void handleMessage(Message msg) { 861 if (DBG) Log.d (TAG, "Message: " + msg.what); 862 switch (msg.what) { 863 case MESSAGE_GET_NAME_AND_ADDRESS: { 864 if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS"); 865 synchronized(mConnection) { 866 //Start bind request 867 if ((mBluetooth == null) && (!mBinding)) { 868 if (DBG) Log.d(TAG, "Binding to service to get name and address"); 869 mConnection.setGetNameAddressOnly(true); 870 //Start bind timeout and bind 871 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 872 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 873 Intent i = new Intent(IBluetooth.class.getName()); 874 if (!doBind(i, mConnection, 875 Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 876 UserHandle.CURRENT)) { 877 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 878 } else { 879 mBinding = true; 880 } 881 } 882 else { 883 Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 884 saveMsg.arg1 = 0; 885 if (mBluetooth != null) { 886 mHandler.sendMessage(saveMsg); 887 } else { 888 // if enable is also called to bind the service 889 // wait for MESSAGE_BLUETOOTH_SERVICE_CONNECTED 890 mHandler.sendMessageDelayed(saveMsg, TIMEOUT_SAVE_MS); 891 } 892 } 893 } 894 break; 895 } 896 case MESSAGE_SAVE_NAME_AND_ADDRESS: { 897 boolean unbind = false; 898 if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS"); 899 synchronized(mConnection) { 900 if (!mEnable && mBluetooth != null) { 901 try { 902 mBluetooth.enable(); 903 } catch (RemoteException e) { 904 Log.e(TAG,"Unable to call enable()",e); 905 } 906 } 907 } 908 if (mBluetooth != null) waitForOnOff(true, false); 909 synchronized(mConnection) { 910 if (mBluetooth != null) { 911 String name = null; 912 String address = null; 913 try { 914 name = mBluetooth.getName(); 915 address = mBluetooth.getAddress(); 916 } catch (RemoteException re) { 917 Log.e(TAG,"",re); 918 } 919 920 if (name != null && address != null) { 921 storeNameAndAddress(name,address); 922 if (mConnection.isGetNameAddressOnly()) { 923 unbind = true; 924 } 925 } else { 926 if (msg.arg1 < MAX_SAVE_RETRIES) { 927 Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 928 retryMsg.arg1= 1+msg.arg1; 929 if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1); 930 mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS); 931 } else { 932 Log.w(TAG,"Maximum name/address remote retrieval retry exceeded"); 933 if (mConnection.isGetNameAddressOnly()) { 934 unbind = true; 935 } 936 } 937 } 938 if (!mEnable) { 939 try { 940 mBluetooth.disable(); 941 } catch (RemoteException e) { 942 Log.e(TAG,"Unable to call disable()",e); 943 } 944 } 945 } else { 946 // rebind service by Request GET NAME AND ADDRESS 947 // if service is unbinded by disable or 948 // MESSAGE_BLUETOOTH_SERVICE_CONNECTED is not received 949 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 950 mHandler.sendMessage(getMsg); 951 } 952 } 953 if (!mEnable && mBluetooth != null) waitForOnOff(false, true); 954 if (unbind) { 955 unbindAndFinish(); 956 } 957 break; 958 } 959 case MESSAGE_ENABLE: 960 if (DBG) { 961 Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 962 } 963 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 964 mEnable = true; 965 handleEnable(msg.arg1 == 1); 966 break; 967 968 case MESSAGE_DISABLE: 969 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 970 if (mEnable && mBluetooth != null) { 971 waitForOnOff(true, false); 972 mEnable = false; 973 handleDisable(); 974 waitForOnOff(false, false); 975 } else { 976 mEnable = false; 977 handleDisable(); 978 } 979 break; 980 981 case MESSAGE_REGISTER_ADAPTER: 982 { 983 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 984 boolean added = mCallbacks.register(callback); 985 Log.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 986 } 987 break; 988 case MESSAGE_UNREGISTER_ADAPTER: 989 { 990 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 991 boolean removed = mCallbacks.unregister(callback); 992 Log.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 993 break; 994 } 995 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 996 { 997 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 998 if (callback != null) { 999 mStateChangeCallbacks.register(callback); 1000 } 1001 break; 1002 } 1003 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 1004 { 1005 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 1006 if (callback != null) { 1007 mStateChangeCallbacks.unregister(callback); 1008 } 1009 break; 1010 } 1011 case MESSAGE_ADD_PROXY_DELAYED: 1012 { 1013 ProfileServiceConnections psc = mProfileServices.get( 1014 new Integer(msg.arg1)); 1015 if (psc == null) { 1016 break; 1017 } 1018 IBluetoothProfileServiceConnection proxy = 1019 (IBluetoothProfileServiceConnection) msg.obj; 1020 psc.addProxy(proxy); 1021 break; 1022 } 1023 case MESSAGE_BIND_PROFILE_SERVICE: 1024 { 1025 ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; 1026 removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); 1027 if (psc == null) { 1028 break; 1029 } 1030 psc.bindService(); 1031 break; 1032 } 1033 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 1034 { 1035 if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 1036 1037 IBinder service = (IBinder) msg.obj; 1038 synchronized(mConnection) { 1039 if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1040 mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); 1041 break; 1042 } // else must be SERVICE_IBLUETOOTH 1043 1044 //Remove timeout 1045 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1046 1047 mBinding = false; 1048 mBluetooth = IBluetooth.Stub.asInterface(service); 1049 1050 try { 1051 boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, 1052 Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); 1053 if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { 1054 Log.e(TAG,"IBluetooth.configHciSnoopLog return false"); 1055 } 1056 } catch (RemoteException e) { 1057 Log.e(TAG,"Unable to call configHciSnoopLog", e); 1058 } 1059 1060 if (mConnection.isGetNameAddressOnly()) { 1061 //Request GET NAME AND ADDRESS 1062 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 1063 mHandler.sendMessage(getMsg); 1064 if (!mEnable) return; 1065 } 1066 1067 mConnection.setGetNameAddressOnly(false); 1068 //Register callback object 1069 try { 1070 mBluetooth.registerCallback(mBluetoothCallback); 1071 } catch (RemoteException re) { 1072 Log.e(TAG, "Unable to register BluetoothCallback",re); 1073 } 1074 //Inform BluetoothAdapter instances that service is up 1075 sendBluetoothServiceUpCallback(); 1076 1077 //Do enable request 1078 try { 1079 if (mQuietEnable == false) { 1080 if(!mBluetooth.enable()) { 1081 Log.e(TAG,"IBluetooth.enable() returned false"); 1082 } 1083 } 1084 else 1085 { 1086 if(!mBluetooth.enableNoAutoConnect()) { 1087 Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1088 } 1089 } 1090 } catch (RemoteException e) { 1091 Log.e(TAG,"Unable to call enable()",e); 1092 } 1093 } 1094 1095 if (!mEnable) { 1096 waitForOnOff(true, false); 1097 handleDisable(); 1098 waitForOnOff(false, false); 1099 } 1100 break; 1101 } 1102 case MESSAGE_TIMEOUT_BIND: { 1103 Log.e(TAG, "MESSAGE_TIMEOUT_BIND"); 1104 synchronized(mConnection) { 1105 mBinding = false; 1106 } 1107 break; 1108 } 1109 case MESSAGE_BLUETOOTH_STATE_CHANGE: 1110 { 1111 int prevState = msg.arg1; 1112 int newState = msg.arg2; 1113 if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 1114 mState = newState; 1115 bluetoothStateChangeHandler(prevState, newState); 1116 // handle error state transition case from TURNING_ON to OFF 1117 // unbind and rebind bluetooth service and enable bluetooth 1118 if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && 1119 (newState == BluetoothAdapter.STATE_OFF) && 1120 (mBluetooth != null) && mEnable) { 1121 recoverBluetoothServiceFromError(); 1122 } 1123 if (newState == BluetoothAdapter.STATE_ON) { 1124 // bluetooth is working, reset the counter 1125 if (mErrorRecoveryRetryCounter != 0) { 1126 Log.w(TAG, "bluetooth is recovered from error"); 1127 mErrorRecoveryRetryCounter = 0; 1128 } 1129 } 1130 break; 1131 } 1132 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 1133 { 1134 Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); 1135 synchronized(mConnection) { 1136 if (msg.arg1 == SERVICE_IBLUETOOTH) { 1137 // if service is unbinded already, do nothing and return 1138 if (mBluetooth == null) break; 1139 mBluetooth = null; 1140 } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { 1141 mBluetoothGatt = null; 1142 break; 1143 } else { 1144 Log.e(TAG, "Bad msg.arg1: " + msg.arg1); 1145 break; 1146 } 1147 } 1148 1149 if (mEnable) { 1150 mEnable = false; 1151 // Send a Bluetooth Restart message 1152 Message restartMsg = mHandler.obtainMessage( 1153 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1154 mHandler.sendMessageDelayed(restartMsg, 1155 SERVICE_RESTART_TIME_MS); 1156 } 1157 1158 if (!mConnection.isGetNameAddressOnly()) { 1159 sendBluetoothServiceDownCallback(); 1160 1161 // Send BT state broadcast to update 1162 // the BT icon correctly 1163 if ((mState == BluetoothAdapter.STATE_TURNING_ON) || 1164 (mState == BluetoothAdapter.STATE_ON)) { 1165 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1166 BluetoothAdapter.STATE_TURNING_OFF); 1167 mState = BluetoothAdapter.STATE_TURNING_OFF; 1168 } 1169 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1170 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1171 BluetoothAdapter.STATE_OFF); 1172 } 1173 1174 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1175 mState = BluetoothAdapter.STATE_OFF; 1176 } 1177 break; 1178 } 1179 case MESSAGE_RESTART_BLUETOOTH_SERVICE: 1180 { 1181 Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 1182 +" Restart IBluetooth service"); 1183 /* Enable without persisting the setting as 1184 it doesnt change when IBluetooth 1185 service restarts */ 1186 mEnable = true; 1187 handleEnable(mQuietEnable); 1188 break; 1189 } 1190 1191 case MESSAGE_TIMEOUT_UNBIND: 1192 { 1193 Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 1194 synchronized(mConnection) { 1195 mUnbinding = false; 1196 } 1197 break; 1198 } 1199 1200 case MESSAGE_USER_SWITCHED: 1201 { 1202 if (DBG) { 1203 Log.d(TAG, "MESSAGE_USER_SWITCHED"); 1204 } 1205 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 1206 /* disable and enable BT when detect a user switch */ 1207 if (mEnable && mBluetooth != null) { 1208 synchronized (mConnection) { 1209 if (mBluetooth != null) { 1210 //Unregister callback object 1211 try { 1212 mBluetooth.unregisterCallback(mBluetoothCallback); 1213 } catch (RemoteException re) { 1214 Log.e(TAG, "Unable to unregister",re); 1215 } 1216 } 1217 } 1218 1219 if (mState == BluetoothAdapter.STATE_TURNING_OFF) { 1220 // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE 1221 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF); 1222 mState = BluetoothAdapter.STATE_OFF; 1223 } 1224 if (mState == BluetoothAdapter.STATE_OFF) { 1225 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_TURNING_ON); 1226 mState = BluetoothAdapter.STATE_TURNING_ON; 1227 } 1228 1229 waitForOnOff(true, false); 1230 1231 if (mState == BluetoothAdapter.STATE_TURNING_ON) { 1232 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 1233 } 1234 1235 unbindAllBluetoothProfileServices(); 1236 // disable 1237 handleDisable(); 1238 // Pbap service need receive STATE_TURNING_OFF intent to close 1239 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 1240 BluetoothAdapter.STATE_TURNING_OFF); 1241 1242 waitForOnOff(false, true); 1243 1244 bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, 1245 BluetoothAdapter.STATE_OFF); 1246 sendBluetoothServiceDownCallback(); 1247 synchronized (mConnection) { 1248 if (mBluetooth != null) { 1249 mBluetooth = null; 1250 //Unbind 1251 mContext.unbindService(mConnection); 1252 } 1253 } 1254 SystemClock.sleep(100); 1255 1256 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1257 mState = BluetoothAdapter.STATE_OFF; 1258 // enable 1259 handleEnable(mQuietEnable); 1260 } else if (mBinding || mBluetooth != null) { 1261 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 1262 userMsg.arg2 = 1 + msg.arg2; 1263 // if user is switched when service is being binding 1264 // delay sending MESSAGE_USER_SWITCHED 1265 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 1266 if (DBG) { 1267 Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 1268 } 1269 } 1270 break; 1271 } 1272 } 1273 } 1274 } 1275 1276 private void handleEnable(boolean quietMode) { 1277 mQuietEnable = quietMode; 1278 1279 synchronized(mConnection) { 1280 if ((mBluetooth == null) && (!mBinding)) { 1281 //Start bind timeout and bind 1282 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 1283 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 1284 mConnection.setGetNameAddressOnly(false); 1285 Intent i = new Intent(IBluetooth.class.getName()); 1286 if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1287 UserHandle.CURRENT)) { 1288 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 1289 } else { 1290 mBinding = true; 1291 } 1292 } else if (mBluetooth != null) { 1293 if (mConnection.isGetNameAddressOnly()) { 1294 // if GetNameAddressOnly is set, we can clear this flag, 1295 // so the service won't be unbind 1296 // after name and address are saved 1297 mConnection.setGetNameAddressOnly(false); 1298 //Register callback object 1299 try { 1300 mBluetooth.registerCallback(mBluetoothCallback); 1301 } catch (RemoteException re) { 1302 Log.e(TAG, "Unable to register BluetoothCallback",re); 1303 } 1304 //Inform BluetoothAdapter instances that service is up 1305 sendBluetoothServiceUpCallback(); 1306 } 1307 1308 //Enable bluetooth 1309 try { 1310 if (!mQuietEnable) { 1311 if(!mBluetooth.enable()) { 1312 Log.e(TAG,"IBluetooth.enable() returned false"); 1313 } 1314 } 1315 else { 1316 if(!mBluetooth.enableNoAutoConnect()) { 1317 Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 1318 } 1319 } 1320 } catch (RemoteException e) { 1321 Log.e(TAG,"Unable to call enable()",e); 1322 } 1323 } 1324 } 1325 } 1326 1327 boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { 1328 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 1329 intent.setComponent(comp); 1330 if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { 1331 Log.e(TAG, "Fail to bind to: " + intent); 1332 return false; 1333 } 1334 return true; 1335 } 1336 1337 private void handleDisable() { 1338 synchronized(mConnection) { 1339 // don't need to disable if GetNameAddressOnly is set, 1340 // service will be unbinded after Name and Address are saved 1341 if ((mBluetooth != null) && (!mConnection.isGetNameAddressOnly())) { 1342 if (DBG) Log.d(TAG,"Sending off request."); 1343 1344 try { 1345 if(!mBluetooth.disable()) { 1346 Log.e(TAG,"IBluetooth.disable() returned false"); 1347 } 1348 } catch (RemoteException e) { 1349 Log.e(TAG,"Unable to call disable()",e); 1350 } 1351 } 1352 } 1353 } 1354 1355 private boolean checkIfCallerIsForegroundUser() { 1356 int foregroundUser; 1357 int callingUser = UserHandle.getCallingUserId(); 1358 int callingUid = Binder.getCallingUid(); 1359 long callingIdentity = Binder.clearCallingIdentity(); 1360 UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 1361 UserInfo ui = um.getProfileParent(callingUser); 1362 int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL; 1363 int callingAppId = UserHandle.getAppId(callingUid); 1364 boolean valid = false; 1365 try { 1366 foregroundUser = ActivityManager.getCurrentUser(); 1367 valid = (callingUser == foregroundUser) || 1368 parentUser == foregroundUser || 1369 callingAppId == Process.NFC_UID || 1370 callingAppId == mSystemUiUid; 1371 if (DBG) { 1372 Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 1373 + " callingUser=" + callingUser 1374 + " parentUser=" + parentUser 1375 + " foregroundUser=" + foregroundUser); 1376 } 1377 } finally { 1378 Binder.restoreCallingIdentity(callingIdentity); 1379 } 1380 return valid; 1381 } 1382 1383 private void bluetoothStateChangeHandler(int prevState, int newState) { 1384 if (prevState != newState) { 1385 //Notify all proxy objects first of adapter state change 1386 if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) { 1387 boolean isUp = (newState==BluetoothAdapter.STATE_ON); 1388 sendBluetoothStateCallback(isUp); 1389 1390 if (isUp) { 1391 // connect to GattService 1392 if (mContext.getPackageManager().hasSystemFeature( 1393 PackageManager.FEATURE_BLUETOOTH_LE)) { 1394 Intent i = new Intent(IBluetoothGatt.class.getName()); 1395 doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 1396 UserHandle.CURRENT); 1397 } 1398 } else { 1399 //If Bluetooth is off, send service down event to proxy objects, and unbind 1400 if (!isUp && canUnbindBluetoothService()) { 1401 unbindAllBluetoothProfileServices(); 1402 sendBluetoothServiceDownCallback(); 1403 unbindAndFinish(); 1404 } 1405 } 1406 } 1407 1408 //Send broadcast message to everyone else 1409 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 1410 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 1411 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1412 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1413 if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState); 1414 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 1415 BLUETOOTH_PERM); 1416 } 1417 } 1418 1419 /** 1420 * if on is true, wait for state become ON 1421 * if off is true, wait for state become OFF 1422 * if both on and off are false, wait for state not ON 1423 */ 1424 private boolean waitForOnOff(boolean on, boolean off) { 1425 int i = 0; 1426 while (i < 10) { 1427 synchronized(mConnection) { 1428 try { 1429 if (mBluetooth == null) break; 1430 if (on) { 1431 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1432 } else if (off) { 1433 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1434 } else { 1435 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 1436 } 1437 } catch (RemoteException e) { 1438 Log.e(TAG, "getState()", e); 1439 break; 1440 } 1441 } 1442 if (on || off) { 1443 SystemClock.sleep(300); 1444 } else { 1445 SystemClock.sleep(50); 1446 } 1447 i++; 1448 } 1449 Log.e(TAG,"waitForOnOff time out"); 1450 return false; 1451 } 1452 1453 private void sendDisableMsg() { 1454 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); 1455 } 1456 1457 private void sendEnableMsg(boolean quietMode) { 1458 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 1459 quietMode ? 1 : 0, 0)); 1460 } 1461 1462 private boolean canUnbindBluetoothService() { 1463 synchronized(mConnection) { 1464 //Only unbind with mEnable flag not set 1465 //For race condition: disable and enable back-to-back 1466 //Avoid unbind right after enable due to callback from disable 1467 //Only unbind with Bluetooth at OFF state 1468 //Only unbind without any MESSAGE_BLUETOOTH_STATE_CHANGE message 1469 try { 1470 if (mEnable || (mBluetooth == null)) return false; 1471 if (mHandler.hasMessages(MESSAGE_BLUETOOTH_STATE_CHANGE)) return false; 1472 return (mBluetooth.getState() == BluetoothAdapter.STATE_OFF); 1473 } catch (RemoteException e) { 1474 Log.e(TAG, "getState()", e); 1475 } 1476 } 1477 return false; 1478 } 1479 1480 private void recoverBluetoothServiceFromError() { 1481 Log.e(TAG,"recoverBluetoothServiceFromError"); 1482 synchronized (mConnection) { 1483 if (mBluetooth != null) { 1484 //Unregister callback object 1485 try { 1486 mBluetooth.unregisterCallback(mBluetoothCallback); 1487 } catch (RemoteException re) { 1488 Log.e(TAG, "Unable to unregister",re); 1489 } 1490 } 1491 } 1492 1493 SystemClock.sleep(500); 1494 1495 // disable 1496 handleDisable(); 1497 1498 waitForOnOff(false, true); 1499 1500 sendBluetoothServiceDownCallback(); 1501 synchronized (mConnection) { 1502 if (mBluetooth != null) { 1503 mBluetooth = null; 1504 //Unbind 1505 mContext.unbindService(mConnection); 1506 } 1507 } 1508 1509 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 1510 mState = BluetoothAdapter.STATE_OFF; 1511 1512 mEnable = false; 1513 1514 if (mErrorRecoveryRetryCounter++ < MAX_ERROR_RESTART_RETRIES) { 1515 // Send a Bluetooth Restart message to reenable bluetooth 1516 Message restartMsg = mHandler.obtainMessage( 1517 MESSAGE_RESTART_BLUETOOTH_SERVICE); 1518 mHandler.sendMessageDelayed(restartMsg, ERROR_RESTART_TIME_MS); 1519 } else { 1520 // todo: notify user to power down and power up phone to make bluetooth work. 1521 } 1522 } 1523 1524 @Override 1525 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1526 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 1527 1528 writer.println("Bluetooth Status"); 1529 writer.println(" enabled: " + mEnable); 1530 writer.println(" state: " + mState); 1531 writer.println(" address: " + mAddress); 1532 writer.println(" name: " + mName + "\n"); 1533 writer.flush(); 1534 1535 if (mBluetooth == null) { 1536 writer.println("Bluetooth Service not connected"); 1537 } else { 1538 try { 1539 ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd); 1540 mBluetooth.dump(pfd); 1541 pfd.close(); 1542 } catch (RemoteException re) { 1543 writer.println("RemoteException while calling Bluetooth Service"); 1544 } catch (IOException re) { 1545 writer.println("IOException attempting to dup() fd"); 1546 } 1547 } 1548 } 1549} 1550