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 package com.android.server; 18 19 import android.app.ActivityManager; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.IBluetooth; 22 import android.bluetooth.IBluetoothCallback; 23 import android.bluetooth.IBluetoothManager; 24 import android.bluetooth.IBluetoothManagerCallback; 25 import android.bluetooth.IBluetoothStateChangeCallback; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.ContentResolver; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.IntentFilter; 32 import android.content.ServiceConnection; 33 import android.os.Binder; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.IBinder; 37 import android.os.Looper; 38 import android.os.Message; 39 import android.os.Process; 40 import android.os.RemoteCallbackList; 41 import android.os.RemoteException; 42 import android.os.SystemClock; 43 import android.os.UserHandle; 44 import android.provider.Settings; 45 import android.util.Log; 46 import java.util.ArrayList; 47 import java.util.List; 48 class BluetoothManagerService extends IBluetoothManager.Stub { 49 private static final String TAG = "BluetoothManagerService"; 50 private static final boolean DBG = true; 51 52 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 53 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 54 private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 55 private static final String EXTRA_ACTION="action"; 56 private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; 57 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 58 private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 59 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 60 private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 61 //Maximum msec to wait for service restart 62 private static final int SERVICE_RESTART_TIME_MS = 200; 63 //Maximum msec to delay MESSAGE_USER_SWITCHED 64 private static final int USER_SWITCHED_TIME_MS = 200; 65 66 private static final int MESSAGE_ENABLE = 1; 67 private static final int MESSAGE_DISABLE = 2; 68 private static final int MESSAGE_REGISTER_ADAPTER = 20; 69 private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 70 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 71 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 72 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 73 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 74 private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; 75 private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60; 76 private static final int MESSAGE_TIMEOUT_BIND =100; 77 private static final int MESSAGE_TIMEOUT_UNBIND =101; 78 private static final int MESSAGE_GET_NAME_AND_ADDRESS=200; 79 private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201; 80 private static final int MESSAGE_USER_SWITCHED = 300; 81 private static final int MAX_SAVE_RETRIES=3; 82 83 private final Context mContext; 84 85 // Locks are not provided for mName and mAddress. 86 // They are accessed in handler or broadcast receiver, same thread context. 87 private String mAddress; 88 private String mName; 89 private final ContentResolver mContentResolver; 90 private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; 91 private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; 92 private IBluetooth mBluetooth; 93 private boolean mBinding; 94 private boolean mUnbinding; 95 private boolean mQuietEnable = false; 96 private boolean mEnable; 97 private int mState; 98 private HandlerThread mThread; 99 private final BluetoothHandler mHandler; 100 101 private void registerForAirplaneMode(IntentFilter filter) { 102 final ContentResolver resolver = mContext.getContentResolver(); 103 final String airplaneModeRadios = Settings.Global.getString(resolver, 104 Settings.Global.AIRPLANE_MODE_RADIOS); 105 final String toggleableRadios = Settings.Global.getString(resolver, 106 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 107 boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 108 airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH); 109 if (mIsAirplaneSensitive) { 110 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 111 } 112 } 113 114 private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { 115 @Override 116 public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { 117 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE,prevState,newState); 118 mHandler.sendMessage(msg); 119 } 120 }; 121 122 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 123 @Override 124 public void onReceive(Context context, Intent intent) { 125 String action = intent.getAction(); 126 if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 127 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 128 if (DBG) Log.d(TAG, "Bluetooth Adapter name changed to " + newName); 129 if (newName != null) { 130 storeNameAndAddress(newName, null); 131 } 132 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 133 if (isAirplaneModeOn()) { 134 // disable without persisting the setting 135 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE, 136 0, 0)); 137 } else if (isBluetoothPersistedStateOn()) { 138 // enable without persisting the setting 139 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, 140 0, 0)); 141 } 142 } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { 143 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, 144 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); 145 } 146 } 147 }; 148 149 BluetoothManagerService(Context context) { 150 mThread = new HandlerThread("BluetoothManager"); 151 mThread.start(); 152 mHandler = new BluetoothHandler(mThread.getLooper()); 153 154 mContext = context; 155 mBluetooth = null; 156 mBinding = false; 157 mUnbinding = false; 158 mEnable = false; 159 mState = BluetoothAdapter.STATE_OFF; 160 mAddress = null; 161 mName = null; 162 mContentResolver = context.getContentResolver(); 163 mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); 164 mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); 165 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 166 filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 167 filter.addAction(Intent.ACTION_USER_SWITCHED); 168 registerForAirplaneMode(filter); 169 mContext.registerReceiver(mReceiver, filter); 170 boolean airplaneModeOn = isAirplaneModeOn(); 171 boolean bluetoothOn = isBluetoothPersistedStateOn(); 172 loadStoredNameAndAddress(); 173 if (DBG) Log.d(TAG, "airplaneModeOn: " + airplaneModeOn + " bluetoothOn: " + bluetoothOn); 174 if (bluetoothOn) { 175 //Enable 176 if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); 177 enableHelper(); 178 } 179 180 if (!isNameAndAddressSet()) { 181 //Sync the Bluetooth name and address from the Bluetooth Adapter 182 if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); 183 getNameAndAddress(); 184 } 185 } 186 187 /** 188 * Returns true if airplane mode is currently on 189 */ 190 private final boolean isAirplaneModeOn() { 191 return Settings.Global.getInt(mContext.getContentResolver(), 192 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 193 } 194 195 /** 196 * Returns true if the Bluetooth saved state is "on" 197 */ 198 private final boolean isBluetoothPersistedStateOn() { 199 return Settings.Global.getInt(mContentResolver, 200 Settings.Global.BLUETOOTH_ON, 0) ==1; 201 } 202 203 /** 204 * Save the Bluetooth on/off state 205 * 206 */ 207 private void persistBluetoothSetting(boolean setOn) { 208 Settings.Global.putInt(mContext.getContentResolver(), 209 Settings.Global.BLUETOOTH_ON, 210 setOn ? 1 : 0); 211 } 212 213 /** 214 * Returns true if the Bluetooth Adapter's name and address is 215 * locally cached 216 * @return 217 */ 218 private boolean isNameAndAddressSet() { 219 return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 220 } 221 222 /** 223 * Retrieve the Bluetooth Adapter's name and address and save it in 224 * in the local cache 225 */ 226 private void loadStoredNameAndAddress() { 227 if (DBG) Log.d(TAG, "Loading stored name and address"); 228 if (mContext.getResources().getBoolean 229 (com.android.internal.R.bool.config_bluetooth_address_validation) && 230 Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) == 0) { 231 // if the valid flag is not set, don't load the address and name 232 if (DBG) Log.d(TAG, "invalid bluetooth name and address stored"); 233 return; 234 } 235 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 236 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 237 if (DBG) Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); 238 } 239 240 /** 241 * Save the Bluetooth name and address in the persistent store. 242 * Only non-null values will be saved. 243 * @param name 244 * @param address 245 */ 246 private void storeNameAndAddress(String name, String address) { 247 if (name != null) { 248 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 249 mName = name; 250 if (DBG) Log.d(TAG,"Stored Bluetooth name: " + 251 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 252 } 253 254 if (address != null) { 255 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 256 mAddress=address; 257 if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " + 258 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 259 } 260 261 if ((name != null) && (address != null)) { 262 Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); 263 } 264 } 265 266 public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 267 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 268 msg.obj = callback; 269 mHandler.sendMessage(msg); 270 synchronized(mConnection) { 271 return mBluetooth; 272 } 273 } 274 275 public void unregisterAdapter(IBluetoothManagerCallback callback) { 276 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 277 "Need BLUETOOTH permission"); 278 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 279 msg.obj = callback; 280 mHandler.sendMessage(msg); 281 } 282 283 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 284 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 285 "Need BLUETOOTH permission"); 286 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 287 msg.obj = callback; 288 mHandler.sendMessage(msg); 289 } 290 291 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 292 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 293 "Need BLUETOOTH permission"); 294 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 295 msg.obj = callback; 296 mHandler.sendMessage(msg); 297 } 298 299 public boolean isEnabled() { 300 if (!checkIfCallerIsForegroundUser()) { 301 Log.w(TAG,"isEnabled(): not allowed for non-active user"); 302 return false; 303 } 304 305 synchronized(mConnection) { 306 try { 307 return (mBluetooth != null && mBluetooth.isEnabled()); 308 } catch (RemoteException e) { 309 Log.e(TAG, "isEnabled()", e); 310 } 311 } 312 return false; 313 } 314 315 public void getNameAndAddress() { 316 if (DBG) { 317 Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth + 318 " mBinding = " + mBinding); 319 } 320 Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 321 mHandler.sendMessage(msg); 322 } 323 public boolean enableNoAutoConnect() 324 { 325 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 326 "Need BLUETOOTH ADMIN permission"); 327 328 if (!checkIfCallerIsForegroundUser()) { 329 Log.w(TAG,"enableNoAutoConnect(): not allowed for non-active user"); 330 return false; 331 } 332 333 if (DBG) { 334 Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth + 335 " mBinding = " + mBinding); 336 } 337 if (Binder.getCallingUid() != Process.NFC_UID) { 338 throw new SecurityException("no permission to enable Bluetooth quietly"); 339 } 340 Message msg = mHandler.obtainMessage(MESSAGE_ENABLE); 341 msg.arg1=0; //No persist 342 msg.arg2=1; //Quiet mode 343 mHandler.sendMessage(msg); 344 return true; 345 346 } 347 public boolean enable() { 348 if (!checkIfCallerIsForegroundUser()) { 349 Log.w(TAG,"enable(): not allowed for non-active user"); 350 return false; 351 } 352 353 return enableHelper(); 354 } 355 356 public boolean disable(boolean persist) { 357 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 358 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 359 360 if (!checkIfCallerIsForegroundUser()) { 361 Log.w(TAG,"disable(): not allowed for non-active user"); 362 return false; 363 } 364 365 if (DBG) { 366 Log.d(TAG,"disable(): mBluetooth = " + mBluetooth + 367 " mBinding = " + mBinding); 368 } 369 370 Message msg = mHandler.obtainMessage(MESSAGE_DISABLE); 371 msg.arg1=(persist?1:0); 372 mHandler.sendMessage(msg); 373 return true; 374 } 375 376 public void unbindAndFinish() { 377 if (DBG) { 378 Log.d(TAG,"unbindAndFinish(): " + mBluetooth + 379 " mBinding = " + mBinding); 380 } 381 382 synchronized (mConnection) { 383 if (mUnbinding) return; 384 mUnbinding = true; 385 if (mBluetooth != null) { 386 if (!mConnection.isGetNameAddressOnly()) { 387 //Unregister callback object 388 try { 389 mBluetooth.unregisterCallback(mBluetoothCallback); 390 } catch (RemoteException re) { 391 Log.e(TAG, "Unable to unregister BluetoothCallback",re); 392 } 393 } 394 if (DBG) Log.d(TAG, "Sending unbind request."); 395 mBluetooth = null; 396 //Unbind 397 mContext.unbindService(mConnection); 398 mUnbinding = false; 399 mBinding = false; 400 } else { 401 mUnbinding=false; 402 } 403 } 404 } 405 406 private void sendBluetoothStateCallback(boolean isUp) { 407 int n = mStateChangeCallbacks.beginBroadcast(); 408 if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers."); 409 for (int i=0; i <n;i++) { 410 try { 411 mStateChangeCallbacks.getBroadcastItem(i).onBluetoothStateChange(isUp); 412 } catch (RemoteException e) { 413 Log.e(TAG, "Unable to call onBluetoothStateChange() on callback #" + i , e); 414 } 415 } 416 mStateChangeCallbacks.finishBroadcast(); 417 } 418 419 /** 420 * Inform BluetoothAdapter instances that Adapter service is up 421 */ 422 private void sendBluetoothServiceUpCallback() { 423 if (!mConnection.isGetNameAddressOnly()) { 424 if (DBG) Log.d(TAG,"Calling onBluetoothServiceUp callbacks"); 425 int n = mCallbacks.beginBroadcast(); 426 Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers."); 427 for (int i=0; i <n;i++) { 428 try { 429 mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); 430 } catch (RemoteException e) { 431 Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); 432 } 433 } 434 mCallbacks.finishBroadcast(); 435 } 436 } 437 /** 438 * Inform BluetoothAdapter instances that Adapter service is down 439 */ 440 private void sendBluetoothServiceDownCallback() { 441 if (!mConnection.isGetNameAddressOnly()) { 442 if (DBG) Log.d(TAG,"Calling onBluetoothServiceDown callbacks"); 443 int n = mCallbacks.beginBroadcast(); 444 Log.d(TAG,"Broadcasting onBluetoothServiceDown() to " + n + " receivers."); 445 for (int i=0; i <n;i++) { 446 try { 447 mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); 448 } catch (RemoteException e) { 449 Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); 450 } 451 } 452 mCallbacks.finishBroadcast(); 453 } 454 } 455 public String getAddress() { 456 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 457 "Need BLUETOOTH ADMIN permission"); 458 459 if (!checkIfCallerIsForegroundUser()) { 460 Log.w(TAG,"getAddress(): not allowed for non-active user"); 461 return mAddress; 462 } 463 464 synchronized(mConnection) { 465 if (mBluetooth != null) { 466 try { 467 return mBluetooth.getAddress(); 468 } catch (RemoteException e) { 469 Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e); 470 } 471 } 472 } 473 // mAddress is accessed from outside. 474 // It is alright without a lock. Here, bluetooth is off, no other thread is 475 // changing mAddress 476 return mAddress; 477 } 478 479 public String getName() { 480 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 481 "Need BLUETOOTH ADMIN permission"); 482 483 if (!checkIfCallerIsForegroundUser()) { 484 Log.w(TAG,"getName(): not allowed for non-active user"); 485 return mName; 486 } 487 488 synchronized(mConnection) { 489 if (mBluetooth != null) { 490 try { 491 return mBluetooth.getName(); 492 } catch (RemoteException e) { 493 Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e); 494 } 495 } 496 } 497 // mName is accessed from outside. 498 // It alright without a lock. Here, bluetooth is off, no other thread is 499 // changing mName 500 return mName; 501 } 502 503 private class BluetoothServiceConnection implements ServiceConnection { 504 505 private boolean mGetNameAddressOnly; 506 507 public void setGetNameAddressOnly(boolean getOnly) { 508 mGetNameAddressOnly = getOnly; 509 } 510 511 public boolean isGetNameAddressOnly() { 512 return mGetNameAddressOnly; 513 } 514 515 public void onServiceConnected(ComponentName className, IBinder service) { 516 if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService"); 517 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 518 msg.obj = service; 519 mHandler.sendMessage(msg); 520 } 521 522 public void onServiceDisconnected(ComponentName className) { 523 // Called if we unexpected disconnected. 524 if (DBG) Log.d(TAG, "BluetoothServiceConnection: disconnected from AdapterService"); 525 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 526 mHandler.sendMessage(msg); 527 } 528 } 529 530 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 531 532 private class BluetoothHandler extends Handler { 533 public BluetoothHandler(Looper looper) { 534 super(looper); 535 } 536 537 @Override 538 public void handleMessage(Message msg) { 539 if (DBG) Log.d (TAG, "Message: " + msg.what); 540 switch (msg.what) { 541 case MESSAGE_GET_NAME_AND_ADDRESS: { 542 if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS"); 543 synchronized(mConnection) { 544 //Start bind request 545 if ((mBluetooth == null) && (!mBinding)) { 546 if (DBG) Log.d(TAG, "Binding to service to get name and address"); 547 mConnection.setGetNameAddressOnly(true); 548 //Start bind timeout and bind 549 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 550 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 551 Intent i = new Intent(IBluetooth.class.getName()); 552 if (!mContext.bindService(i, mConnection, 553 Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) { 554 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 555 Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName()); 556 } else { 557 mBinding = true; 558 } 559 } 560 else { 561 Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 562 saveMsg.arg1 = 0; 563 if (mBluetooth != null) { 564 mHandler.sendMessage(saveMsg); 565 } else { 566 // if enable is also called to bind the service 567 // wait for MESSAGE_BLUETOOTH_SERVICE_CONNECTED 568 mHandler.sendMessageDelayed(saveMsg, TIMEOUT_SAVE_MS); 569 } 570 } 571 } 572 break; 573 } 574 case MESSAGE_SAVE_NAME_AND_ADDRESS: { 575 boolean unbind = false; 576 if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS"); 577 synchronized(mConnection) { 578 if (!mEnable && mBluetooth != null) { 579 try { 580 mBluetooth.enable(); 581 } catch (RemoteException e) { 582 Log.e(TAG,"Unable to call enable()",e); 583 } 584 } 585 } 586 if (mBluetooth != null) waitForOnOff(true, false); 587 synchronized(mConnection) { 588 if (mBluetooth != null) { 589 String name = null; 590 String address = null; 591 try { 592 name = mBluetooth.getName(); 593 address = mBluetooth.getAddress(); 594 } catch (RemoteException re) { 595 Log.e(TAG,"",re); 596 } 597 598 if (name != null && address != null) { 599 storeNameAndAddress(name,address); 600 if (mConnection.isGetNameAddressOnly()) { 601 unbind = true; 602 } 603 } else { 604 if (msg.arg1 < MAX_SAVE_RETRIES) { 605 Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 606 retryMsg.arg1= 1+msg.arg1; 607 if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1); 608 mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS); 609 } else { 610 Log.w(TAG,"Maximum name/address remote retrieval retry exceeded"); 611 if (mConnection.isGetNameAddressOnly()) { 612 unbind = true; 613 } 614 } 615 } 616 if (!mEnable) { 617 try { 618 mBluetooth.disable(); 619 } catch (RemoteException e) { 620 Log.e(TAG,"Unable to call disable()",e); 621 } 622 } 623 } else { 624 // rebind service by Request GET NAME AND ADDRESS 625 // if service is unbinded by disable or 626 // MESSAGE_BLUETOOTH_SERVICE_CONNECTED is not received 627 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 628 mHandler.sendMessage(getMsg); 629 } 630 } 631 if (!mEnable && mBluetooth != null) waitForOnOff(false, true); 632 if (unbind) { 633 unbindAndFinish(); 634 } 635 break; 636 } 637 case MESSAGE_ENABLE: 638 if (DBG) { 639 Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth); 640 } 641 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 642 mEnable = true; 643 handleEnable(msg.arg1 == 1, msg.arg2 ==1); 644 break; 645 646 case MESSAGE_DISABLE: 647 mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); 648 if (mEnable && mBluetooth != null) { 649 waitForOnOff(true, false); 650 mEnable = false; 651 handleDisable(msg.arg1 == 1); 652 waitForOnOff(false, false); 653 } else { 654 mEnable = false; 655 handleDisable(msg.arg1 == 1); 656 } 657 break; 658 659 case MESSAGE_REGISTER_ADAPTER: 660 { 661 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 662 boolean added = mCallbacks.register(callback); 663 Log.d(TAG,"Added callback: " + (callback == null? "null": callback) +":" +added ); 664 } 665 break; 666 case MESSAGE_UNREGISTER_ADAPTER: 667 { 668 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 669 boolean removed = mCallbacks.unregister(callback); 670 Log.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed); 671 break; 672 } 673 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 674 { 675 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 676 mStateChangeCallbacks.register(callback); 677 break; 678 } 679 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 680 { 681 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 682 mStateChangeCallbacks.unregister(callback); 683 break; 684 } 685 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 686 { 687 if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED"); 688 689 //Remove timeout 690 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 691 692 IBinder service = (IBinder) msg.obj; 693 synchronized(mConnection) { 694 mBinding = false; 695 mBluetooth = IBluetooth.Stub.asInterface(service); 696 697 if (mConnection.isGetNameAddressOnly()) { 698 //Request GET NAME AND ADDRESS 699 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 700 mHandler.sendMessage(getMsg); 701 if (!mEnable) return; 702 } 703 704 mConnection.setGetNameAddressOnly(false); 705 //Register callback object 706 try { 707 mBluetooth.registerCallback(mBluetoothCallback); 708 } catch (RemoteException re) { 709 Log.e(TAG, "Unable to register BluetoothCallback",re); 710 } 711 //Inform BluetoothAdapter instances that service is up 712 sendBluetoothServiceUpCallback(); 713 714 //Do enable request 715 try { 716 if (mQuietEnable == false) { 717 if(!mBluetooth.enable()) { 718 Log.e(TAG,"IBluetooth.enable() returned false"); 719 } 720 } 721 else 722 { 723 if(!mBluetooth.enableNoAutoConnect()) { 724 Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 725 } 726 } 727 } catch (RemoteException e) { 728 Log.e(TAG,"Unable to call enable()",e); 729 } 730 } 731 732 if (!mEnable) { 733 waitForOnOff(true, false); 734 handleDisable(false); 735 waitForOnOff(false, false); 736 } 737 break; 738 } 739 case MESSAGE_TIMEOUT_BIND: { 740 Log.e(TAG, "MESSAGE_TIMEOUT_BIND"); 741 synchronized(mConnection) { 742 mBinding = false; 743 } 744 break; 745 } 746 case MESSAGE_BLUETOOTH_STATE_CHANGE: 747 { 748 int prevState = msg.arg1; 749 int newState = msg.arg2; 750 if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_STATE_CHANGE: prevState = " + prevState + ", newState=" + newState); 751 mState = newState; 752 bluetoothStateChangeHandler(prevState, newState); 753 break; 754 } 755 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 756 { 757 Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED"); 758 synchronized(mConnection) { 759 // if service is unbinded already, do nothing and return 760 if (mBluetooth == null) return; 761 mBluetooth = null; 762 } 763 764 if (mEnable) { 765 mEnable = false; 766 // Send a Bluetooth Restart message 767 Message restartMsg = mHandler.obtainMessage( 768 MESSAGE_RESTART_BLUETOOTH_SERVICE); 769 mHandler.sendMessageDelayed(restartMsg, 770 SERVICE_RESTART_TIME_MS); 771 } 772 773 if (!mConnection.isGetNameAddressOnly()) { 774 sendBluetoothServiceDownCallback(); 775 776 // Send BT state broadcast to update 777 // the BT icon correctly 778 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 779 BluetoothAdapter.STATE_TURNING_OFF); 780 mState = BluetoothAdapter.STATE_OFF; 781 } 782 break; 783 } 784 case MESSAGE_RESTART_BLUETOOTH_SERVICE: 785 { 786 Log.d(TAG, "MESSAGE_RESTART_BLUETOOTH_SERVICE:" 787 +" Restart IBluetooth service"); 788 /* Enable without persisting the setting as 789 it doesnt change when IBluetooth 790 service restarts */ 791 mEnable = true; 792 handleEnable(false, mQuietEnable); 793 break; 794 } 795 796 case MESSAGE_TIMEOUT_UNBIND: 797 { 798 Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 799 synchronized(mConnection) { 800 mUnbinding = false; 801 } 802 break; 803 } 804 805 case MESSAGE_USER_SWITCHED: 806 { 807 if (DBG) { 808 Log.d(TAG, "MESSAGE_USER_SWITCHED"); 809 } 810 mHandler.removeMessages(MESSAGE_USER_SWITCHED); 811 /* disable and enable BT when detect a user switch */ 812 if (mEnable && mBluetooth != null) { 813 synchronized (mConnection) { 814 if (mBluetooth != null) { 815 //Unregister callback object 816 try { 817 mBluetooth.unregisterCallback(mBluetoothCallback); 818 } catch (RemoteException re) { 819 Log.e(TAG, "Unable to unregister",re); 820 } 821 } 822 } 823 mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); 824 825 waitForOnOff(true, false); 826 827 bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); 828 829 // disable 830 handleDisable(false); 831 832 waitForOnOff(false, true); 833 834 bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, 835 BluetoothAdapter.STATE_OFF); 836 mState = BluetoothAdapter.STATE_OFF; 837 sendBluetoothServiceDownCallback(); 838 synchronized (mConnection) { 839 if (mBluetooth != null) { 840 mBluetooth = null; 841 //Unbind 842 mContext.unbindService(mConnection); 843 } 844 } 845 SystemClock.sleep(100); 846 847 // enable 848 handleEnable(false, mQuietEnable); 849 } else if (mBinding || mBluetooth != null) { 850 Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED); 851 userMsg.arg2 = 1 + msg.arg2; 852 // if user is switched when service is being binding 853 // delay sending MESSAGE_USER_SWITCHED 854 mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS); 855 if (DBG) { 856 Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2); 857 } 858 } 859 break; 860 } 861 } 862 } 863 } 864 865 private void handleEnable(boolean persist, boolean quietMode) { 866 if (persist) { 867 persistBluetoothSetting(true); 868 } 869 870 mQuietEnable = quietMode; 871 872 synchronized(mConnection) { 873 if ((mBluetooth == null) && (!mBinding)) { 874 //Start bind timeout and bind 875 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 876 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 877 mConnection.setGetNameAddressOnly(false); 878 Intent i = new Intent(IBluetooth.class.getName()); 879 if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE, 880 UserHandle.USER_CURRENT)) { 881 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 882 Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName()); 883 } else { 884 mBinding = true; 885 } 886 } else if (mBluetooth != null) { 887 if (mConnection.isGetNameAddressOnly()) { 888 // if GetNameAddressOnly is set, we can clear this flag, 889 // so the service won't be unbind 890 // after name and address are saved 891 mConnection.setGetNameAddressOnly(false); 892 //Register callback object 893 try { 894 mBluetooth.registerCallback(mBluetoothCallback); 895 } catch (RemoteException re) { 896 Log.e(TAG, "Unable to register BluetoothCallback",re); 897 } 898 //Inform BluetoothAdapter instances that service is up 899 sendBluetoothServiceUpCallback(); 900 } 901 902 //Enable bluetooth 903 try { 904 if (!mQuietEnable) { 905 if(!mBluetooth.enable()) { 906 Log.e(TAG,"IBluetooth.enable() returned false"); 907 } 908 } 909 else { 910 if(!mBluetooth.enableNoAutoConnect()) { 911 Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false"); 912 } 913 } 914 } catch (RemoteException e) { 915 Log.e(TAG,"Unable to call enable()",e); 916 } 917 } 918 } 919 } 920 921 private void handleDisable(boolean persist) { 922 if (persist) { 923 persistBluetoothSetting(false); 924 } 925 926 synchronized(mConnection) { 927 // don't need to disable if GetNameAddressOnly is set, 928 // service will be unbinded after Name and Address are saved 929 if ((mBluetooth != null) && (!mConnection.isGetNameAddressOnly())) { 930 if (DBG) Log.d(TAG,"Sending off request."); 931 932 try { 933 if(!mBluetooth.disable()) { 934 Log.e(TAG,"IBluetooth.disable() returned false"); 935 } 936 } catch (RemoteException e) { 937 Log.e(TAG,"Unable to call disable()",e); 938 } 939 } 940 } 941 } 942 943 private boolean checkIfCallerIsForegroundUser() { 944 int foregroundUser; 945 int callingUser = UserHandle.getCallingUserId(); 946 long callingIdentity = Binder.clearCallingIdentity(); 947 boolean valid = false; 948 try { 949 foregroundUser = ActivityManager.getCurrentUser(); 950 valid = (callingUser == foregroundUser); 951 if (DBG) { 952 Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid 953 + " callingUser=" + callingUser 954 + " foregroundUser=" + foregroundUser); 955 } 956 } finally { 957 Binder.restoreCallingIdentity(callingIdentity); 958 } 959 return valid; 960 } 961 962 private boolean enableHelper() { 963 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 964 "Need BLUETOOTH ADMIN permission"); 965 if (DBG) { 966 Log.d(TAG,"enable(): mBluetooth =" + mBluetooth + 967 " mBinding = " + mBinding); 968 } 969 970 Message msg = mHandler.obtainMessage(MESSAGE_ENABLE); 971 msg.arg1=1; //persist 972 msg.arg2=0; //No Quiet Mode 973 mHandler.sendMessage(msg); 974 return true; 975 } 976 977 private void bluetoothStateChangeHandler(int prevState, int newState) { 978 if (prevState != newState) { 979 //Notify all proxy objects first of adapter state change 980 if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) { 981 boolean isUp = (newState==BluetoothAdapter.STATE_ON); 982 sendBluetoothStateCallback(isUp); 983 984 //If Bluetooth is off, send service down event to proxy objects, and unbind 985 if (!isUp) { 986 //Only unbind with mEnable flag not set 987 //For race condition: disable and enable back-to-back 988 //Avoid unbind right after enable due to callback from disable 989 if ((!mEnable) && (mBluetooth != null)) { 990 sendBluetoothServiceDownCallback(); 991 unbindAndFinish(); 992 } 993 } 994 } 995 996 //Send broadcast message to everyone else 997 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 998 intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); 999 intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); 1000 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1001 if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState); 1002 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 1003 BLUETOOTH_PERM); 1004 } 1005 } 1006 1007 /** 1008 * if on is true, wait for state become ON 1009 * if off is true, wait for state become OFF 1010 * if both on and off are false, wait for state not ON 1011 */ 1012 private boolean waitForOnOff(boolean on, boolean off) { 1013 int i = 0; 1014 while (i < 10) { 1015 synchronized(mConnection) { 1016 try { 1017 if (mBluetooth == null) break; 1018 if (on) { 1019 if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; 1020 } else if (off) { 1021 if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; 1022 } else { 1023 if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; 1024 } 1025 } catch (RemoteException e) { 1026 Log.e(TAG, "getState()", e); 1027 break; 1028 } 1029 } 1030 if (on || off) { 1031 SystemClock.sleep(300); 1032 } else { 1033 SystemClock.sleep(50); 1034 } 1035 i++; 1036 } 1037 Log.e(TAG,"waitForOnOff time out"); 1038 return false; 1039 } 1040 } 1041