BluetoothManagerService.java revision 116d1d4696ac8e300c83dd8a95e20e67717ef520
1/* 2 * Copyright (C) 2012 Google Inc. 3 */ 4 5package com.android.server; 6 7import android.bluetooth.BluetoothAdapter; 8import android.bluetooth.IBluetooth; 9import android.bluetooth.IBluetoothManager; 10import android.bluetooth.IBluetoothManagerCallback; 11import android.bluetooth.IBluetoothStateChangeCallback; 12import android.content.BroadcastReceiver; 13import android.content.ComponentName; 14import android.content.ContentResolver; 15import android.content.Context; 16import android.content.Intent; 17import android.content.IntentFilter; 18import android.content.ServiceConnection; 19import android.os.Handler; 20import android.os.IBinder; 21import android.os.Message; 22import android.os.RemoteException; 23import android.provider.Settings; 24import android.util.Log; 25import java.util.List; 26import java.util.ArrayList; 27 28class BluetoothManagerService extends IBluetoothManager.Stub { 29 private static final String TAG = "BluetoothManagerService"; 30 private static final boolean DBG = true; 31 32 private static final boolean ALWAYS_SYNC_NAME_ADDRESS=true; //If true, always load name and address 33 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; 34 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 35 private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED"; 36 private static final String EXTRA_ACTION="action"; 37 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; 38 private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; 39 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind 40 private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save 41 42 private static final int MESSAGE_ENABLE = 1; 43 private static final int MESSAGE_DISABLE = 2; 44 private static final int MESSAGE_AIRPLANE_MODE_OFF=10; 45 private static final int MESSAGE_AIRPLANE_MODE_ON=11; 46 private static final int MESSAGE_REGISTER_ADAPTER = 20; 47 private static final int MESSAGE_UNREGISTER_ADAPTER = 21; 48 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; 49 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; 50 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; 51 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41; 52 private static final int MESSAGE_BLUETOOTH_ON = 50; 53 private static final int MESSAGE_BLUETOOTH_OFF = 51; 54 private static final int MESSAGE_TIMEOUT_BIND =100; 55 private static final int MESSAGE_TIMEOUT_UNBIND =101; 56 private static final int MESSAGE_GET_NAME_AND_ADDRESS=200; 57 private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201; 58 private static final int MAX_SAVE_RETRIES=3; 59 60 private final Context mContext; 61 private String mAddress; 62 private String mName; 63 private ContentResolver mContentResolver; 64 private List<IBluetoothManagerCallback> mCallbacks; 65 private List<IBluetoothStateChangeCallback> mStateChangeCallbacks; 66 private IBluetooth mBluetooth; 67 private boolean mBinding; 68 private boolean mUnbinding; 69 70 private void registerForAirplaneMode(IntentFilter filter) { 71 final ContentResolver resolver = mContext.getContentResolver(); 72 final String airplaneModeRadios = Settings.System.getString(resolver, 73 Settings.System.AIRPLANE_MODE_RADIOS); 74 final String toggleableRadios = Settings.System.getString(resolver, 75 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS); 76 boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true : 77 airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH); 78 if (mIsAirplaneSensitive) { 79 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 80 } 81 } 82 83 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 String action = intent.getAction(); 87 if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { 88 int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); 89 if (state == BluetoothAdapter.STATE_OFF) { 90 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_OFF); 91 mHandler.sendMessage(msg); 92 } else if (state == BluetoothAdapter.STATE_ON) { 93 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_ON); 94 mHandler.sendMessage(msg); 95 } 96 } else if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { 97 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); 98 Log.d(TAG, "Bluetooth Adapter name changed to " + newName); 99 if (newName != null) { 100 storeNameAndAddress(newName, null); 101 } 102 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 103 if (isAirplaneModeOn()) { 104 Message msg = mHandler.obtainMessage(MESSAGE_AIRPLANE_MODE_ON); 105 msg.arg1=0; 106 mHandler.sendMessage(msg); 107 } else { 108 Message msg = mHandler.obtainMessage(MESSAGE_AIRPLANE_MODE_OFF); 109 msg.arg1=0; 110 mHandler.sendMessage(msg); 111 } 112 } 113 } 114 }; 115 116 BluetoothManagerService(Context context) { 117 mContext = context; 118 mBluetooth = null; 119 mBinding = false; 120 mUnbinding = false; 121 mAddress = null; 122 mName = null; 123 mContentResolver = context.getContentResolver(); 124 mCallbacks = new ArrayList<IBluetoothManagerCallback>(); 125 mStateChangeCallbacks = new ArrayList<IBluetoothStateChangeCallback>(); 126 IntentFilter mFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 127 mFilter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); 128 registerForAirplaneMode(mFilter); 129 mContext.registerReceiver(mReceiver, mFilter); 130 boolean airplaneModeOn = isAirplaneModeOn(); 131 boolean bluetoothOn = isBluetoothPersistedStateOn(); 132 loadStoredNameAndAddress(); 133 if (DBG) Log.d(TAG, "airplaneModeOn: " + airplaneModeOn + " bluetoothOn: " + bluetoothOn); 134 if (!airplaneModeOn && bluetoothOn) { 135 //Enable 136 if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); 137 enable(); 138 } else if (ALWAYS_SYNC_NAME_ADDRESS || !isNameAndAddressSet()) { 139 //Sync the Bluetooth name and address from the Bluetooth Adapter 140 if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); 141 getNameAndAddress(); 142 } 143 } 144 145 /** 146 * Returns true if airplane mode is currently on 147 */ 148 private final boolean isAirplaneModeOn() { 149 return Settings.System.getInt(mContext.getContentResolver(), 150 Settings.System.AIRPLANE_MODE_ON, 0) == 1; 151 } 152 153 /** 154 * Returns true if the Bluetooth saved state is "on" 155 */ 156 private final boolean isBluetoothPersistedStateOn() { 157 return Settings.Secure.getInt(mContentResolver, 158 Settings.Secure.BLUETOOTH_ON, 0) ==1; 159 } 160 161 /** 162 * Save the Bluetooth on/off state 163 * 164 */ 165 private void persistBluetoothSetting(boolean setOn) { 166 Settings.Secure.putInt(mContext.getContentResolver(), 167 Settings.Secure.BLUETOOTH_ON, 168 setOn ? 1 : 0); 169 } 170 171 /** 172 * Returns true if the Bluetooth Adapter's name and address is 173 * locally cached 174 * @return 175 */ 176 private boolean isNameAndAddressSet() { 177 return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0; 178 } 179 180 /** 181 * Retrieve the Bluetooth Adapter's name and address and save it in 182 * in the local cache 183 */ 184 private void loadStoredNameAndAddress() { 185 if (DBG) Log.d(TAG, "Loading stored name and address"); 186 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); 187 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); 188 if (mName == null || mAddress == null) { 189 if (DBG) Log.d(TAG, "Name or address not cached..."); 190 } 191 } 192 193 /** 194 * Save the Bluetooth name and address in the persistent store. 195 * Only non-null values will be saved. 196 * @param name 197 * @param address 198 */ 199 private void storeNameAndAddress(String name, String address) { 200 if (name != null) { 201 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); 202 mName = name; 203 if (DBG) Log.d(TAG,"Stored Bluetooth name: " + 204 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME)); 205 } 206 207 if (address != null) { 208 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); 209 mAddress=address; 210 if (DBG) Log.d(TAG,"Stored Bluetoothaddress: " + 211 Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS)); 212 } 213 } 214 215 public IBluetooth registerAdapter(IBluetoothManagerCallback callback){ 216 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 217 "Need BLUETOOTH permission"); 218 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); 219 msg.obj = callback; 220 mHandler.sendMessage(msg); 221 synchronized(mConnection) { 222 return mBluetooth; 223 } 224 } 225 226 public void unregisterAdapter(IBluetoothManagerCallback callback) { 227 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 228 "Need BLUETOOTH permission"); 229 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); 230 msg.obj = callback; 231 mHandler.sendMessage(msg); 232 } 233 234 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { 235 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 236 "Need BLUETOOTH permission"); 237 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK); 238 msg.obj = callback; 239 mHandler.sendMessage(msg); 240 } 241 242 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) { 243 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, 244 "Need BLUETOOTH permission"); 245 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK); 246 msg.obj = callback; 247 mHandler.sendMessage(msg); 248 } 249 250 public boolean isEnabled() { 251 synchronized(mConnection) { 252 try { 253 return (mBluetooth != null && mBluetooth.isEnabled()); 254 } catch (RemoteException e) { 255 Log.e(TAG, "isEnabled()", e); 256 } 257 } 258 return false; 259 } 260 261 private boolean isConnected() { 262 return mBluetooth != null; 263 } 264 265 public void getNameAndAddress() { 266 if (DBG) { 267 Log.d(TAG,"getNameAndAddress(): mBluetooth = " + 268 (mBluetooth==null?"null":mBluetooth) + 269 " mBinding = " + mBinding + 270 " isConnected = " + isConnected()); 271 } 272 synchronized(mConnection) { 273 if (mBinding) return ; 274 if (!isConnected()) mBinding = true; 275 } 276 Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 277 mHandler.sendMessage(msg); 278 } 279 280 public boolean enable() { 281 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 282 "Need BLUETOOTH ADMIN permission"); 283 if (DBG) { 284 Log.d(TAG,"enable(): mBluetooth =" + 285 (mBluetooth==null?"null":mBluetooth) + 286 " mBinding = " + mBinding + 287 " isConnected = " + isConnected()); 288 } 289 290 synchronized(mConnection) { 291 //if (mBluetooth != null) return false; 292 if (mBinding) { 293 Log.w(TAG,"enable(): binding in progress. Returning.."); 294 return true; 295 } 296 if (!isConnected()) mBinding = true; 297 } 298 299 Message msg = mHandler.obtainMessage(MESSAGE_ENABLE); 300 msg.arg1=1; //persist 301 mHandler.sendMessage(msg); 302 return true; 303 } 304 305 public boolean disable(boolean persist) { 306 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 307 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson"); 308 if (DBG) { 309 Log.d(TAG,"disable(): mBluetooth = " + 310 (mBluetooth==null?"null":mBluetooth) + 311 " mBinding = " + mBinding + 312 " isConnected = " + isConnected());} 313 314 synchronized(mConnection) { 315 if (mBluetooth == null) return false; 316 } 317 Message msg = mHandler.obtainMessage(MESSAGE_DISABLE); 318 msg.arg1=(persist?1:0); 319 mHandler.sendMessage(msg); 320 return true; 321 } 322 323 public void unbindAndFinish() { 324 if (DBG) { 325 Log.d(TAG,"unbindAndFinish(): " + 326 (mBluetooth==null?"null":mBluetooth) + 327 " mBinding = " + mBinding + 328 " isConnected = " + isConnected()); 329 } 330 331 synchronized (mConnection) { 332 if (mUnbinding) return; 333 mUnbinding = true; 334 if (isConnected()) { 335 if (DBG) Log.d(TAG, "Sending unbind request."); 336 mContext.unbindService(mConnection); 337 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED)); 338 } else { 339 mUnbinding=false; 340 } 341 } 342 } 343 344 public String getAddress() { 345 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 346 "Need BLUETOOTH ADMIN permission"); 347 synchronized(mConnection) { 348 if (mBluetooth != null) { 349 try { 350 return mBluetooth.getAddress(); 351 } catch (RemoteException e) { 352 Log.e(TAG, "getAddress(): Unable to retrieve address remotely..Returning cached address",e); 353 } 354 } 355 } 356 return mAddress; 357 } 358 359 public String getName() { 360 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 361 "Need BLUETOOTH ADMIN permission"); 362 synchronized(mConnection) { 363 if (mBluetooth != null) { 364 try { 365 return mBluetooth.getName(); 366 } catch (RemoteException e) { 367 Log.e(TAG, "getName(): Unable to retrieve name remotely..Returning cached name",e); 368 } 369 } 370 } 371 return mName; 372 } 373 374 private class BluetoothServiceConnection implements ServiceConnection { 375 376 private boolean mGetNameAddressOnly; 377 378 public void setGetNameAddressOnly(boolean getOnly) { 379 mGetNameAddressOnly = getOnly; 380 } 381 382 public boolean isGetNameAddressOnly() { 383 return mGetNameAddressOnly; 384 } 385 386 public void onServiceConnected(ComponentName className, IBinder service) { 387 if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService"); 388 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); 389 msg.obj = service; 390 mHandler.sendMessage(msg); 391 } 392 393 public void onServiceDisconnected(ComponentName className) { 394 // Called if we unexpected disconnected. 395 if (DBG) Log.d(TAG, "BluetoothServiceConnection: disconnected from AdapterService"); 396 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); 397 mHandler.sendMessage(msg); 398 } 399 } 400 401 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); 402 403 private final Handler mHandler = new Handler() { 404 @Override 405 public void handleMessage(Message msg) { 406 if (DBG) Log.d (TAG, "Message: " + msg.what); 407 switch (msg.what) { 408 case MESSAGE_GET_NAME_AND_ADDRESS: { 409 if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS"); 410 if (mBluetooth == null) { 411 //Start bind request 412 if (!isConnected()) { 413 if (DBG) Log.d(TAG, "Binding to service to get name and address"); 414 mConnection.setGetNameAddressOnly(true); 415 //Start bind timeout and bind 416 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 417 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 418 Intent i = new Intent(IBluetooth.class.getName()); 419 if (!mContext.bindService(i, mConnection, 420 Context.BIND_AUTO_CREATE)) { 421 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 422 Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName()); 423 } 424 } 425 } else { 426 Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 427 mHandler.sendMessage(saveMsg); 428 } 429 } 430 break; 431 case MESSAGE_SAVE_NAME_AND_ADDRESS: { 432 if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS"); 433 if (mBluetooth != null) { 434 String name = null; 435 String address = null; 436 try { 437 name = mBluetooth.getName(); 438 address = mBluetooth.getAddress(); 439 } catch (RemoteException re) { 440 Log.e(TAG,"",re); 441 } 442 443 if (name != null && address != null) { 444 storeNameAndAddress(name,address); 445 Intent i = new Intent(IBluetooth.class.getName()); 446 i.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 447 i.putExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.STATE_OFF); 448 mContext.startService(i); 449 unbindAndFinish(); 450 } else { 451 if (msg.arg1 < MAX_SAVE_RETRIES) { 452 Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS); 453 retryMsg.arg1= 1+msg.arg1; 454 if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1); 455 mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS); 456 } else { 457 Log.w(TAG,"Maximum name/address remote retrieval retry exceeded"); 458 unbindAndFinish(); 459 } 460 } 461 } 462 } 463 break; 464 case MESSAGE_AIRPLANE_MODE_OFF: { 465 if (DBG) Log.d(TAG,"MESSAGE_AIRPLANE_MODE_OFF"); 466 //Check if we should turn on bluetooth 467 if (!isBluetoothPersistedStateOn()) { 468 if (DBG)Log.d(TAG, "Bluetooth persisted state is off. Not turning on Bluetooth."); 469 return; 470 } 471 //Fall through to MESSAGE_ENABLE 472 } 473 case MESSAGE_ENABLE: { 474 if (DBG) { 475 Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth + 476 " isConnected = " + isConnected()); 477 } 478 boolean persist = (1==msg.arg1); 479 if (persist) { 480 persistBluetoothSetting(true); 481 } 482 if (mBluetooth == null) { 483 //Start bind request 484 if (!isConnected()) { 485 //Start bind timeout and bind 486 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); 487 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); 488 Intent i = new Intent(IBluetooth.class.getName()); 489 i.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 490 i.putExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.STATE_ON); 491 mContext.startService(i); 492 mConnection.setGetNameAddressOnly(false); 493 if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE)) { 494 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 495 Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName()); 496 } 497 } 498 } else { 499 //Check if name and address is loaded if not get it first. 500 if (ALWAYS_SYNC_NAME_ADDRESS || !isNameAndAddressSet()) { 501 try { 502 if (DBG) Log.d(TAG,"Getting and storing Bluetooth name and address prior to enable."); 503 storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress()); 504 } catch (RemoteException e) {Log.e(TAG, "", e);}; 505 } 506 Intent i = new Intent(IBluetooth.class.getName()); 507 i.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 508 i.putExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.STATE_ON); 509 mContext.startService(i); 510 } 511 // TODO(BT) what if service failed to start: 512 // [fc] fixed: watch for bind timeout and handle accordingly 513 // TODO(BT) persist the setting depending on argument 514 // [fc]: let AdapterServiceHandle 515 } 516 break; 517 case MESSAGE_AIRPLANE_MODE_ON:; 518 if (DBG) { 519 Log.d(TAG, "MESSAGE_AIRPLANE_MODE_ON: mBluetooth = " + mBluetooth + 520 " isConnected = " + isConnected()); 521 //Fall through to MESSAGE_DISABLE 522 } 523 case MESSAGE_DISABLE: 524 if (mBluetooth != null ) { 525 boolean persist = (1==msg.arg1); 526 if (persist) { 527 persistBluetoothSetting(false); 528 } 529 mConnection.setGetNameAddressOnly(false); 530 if (DBG) Log.d(TAG,"Sending off request."); 531 Intent i = new Intent(IBluetooth.class.getName()); 532 i.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED); 533 i.putExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.STATE_OFF); 534 mContext.startService(i); 535 } 536 // TODO(BT) what if service failed to stop: 537 // [fc] fixed: watch for disable event and unbind accordingly 538 // TODO(BT) persist the setting depending on argument 539 // [fc]: let AdapterServiceHandle 540 541 break; 542 case MESSAGE_REGISTER_ADAPTER: 543 { 544 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 545 mCallbacks.add(callback); 546 } 547 break; 548 case MESSAGE_UNREGISTER_ADAPTER: 549 { 550 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; 551 mCallbacks.remove(callback); 552 } 553 break; 554 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: 555 { 556 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 557 mStateChangeCallbacks.add(callback); 558 } 559 break; 560 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: 561 { 562 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; 563 mStateChangeCallbacks.remove(callback); 564 } 565 break; 566 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: 567 { 568 if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED"); 569 570 //Remove timeout 571 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); 572 573 IBinder service = (IBinder) msg.obj; 574 synchronized(mConnection) { 575 mBinding = false; 576 mBluetooth = IBluetooth.Stub.asInterface(service); 577 } 578 579 if (mConnection.isGetNameAddressOnly()) { 580 //Request GET NAME AND ADDRESS 581 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); 582 mHandler.sendMessage(getMsg); 583 return; 584 } 585 586 try { 587 for (IBluetoothManagerCallback callback : mCallbacks) { 588 callback.onBluetoothServiceUp(mBluetooth); 589 } 590 } catch (RemoteException e) { 591 Log.e(TAG, "", e); 592 } 593 594 } 595 break; 596 case MESSAGE_TIMEOUT_BIND: { 597 Log.e(TAG, "MESSAGE_TIMEOUT_BIND"); 598 synchronized(mConnection) { 599 mBinding = false; 600 } 601 } 602 break; 603 case MESSAGE_BLUETOOTH_ON: 604 { 605 if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_ON"); 606 try { 607 for (IBluetoothStateChangeCallback callback : mStateChangeCallbacks) { 608 callback.onBluetoothStateChange(true); 609 } 610 } catch (RemoteException e) { 611 Log.e(TAG, "", e); 612 } 613 } 614 break; 615 case MESSAGE_BLUETOOTH_OFF: 616 { 617 if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_OFF"); 618 try { 619 for (IBluetoothStateChangeCallback callback : mStateChangeCallbacks) { 620 callback.onBluetoothStateChange(false); 621 } 622 } catch (RemoteException e) { 623 Log.e(TAG, "", e); 624 } 625 unbindAndFinish(); 626 } 627 break; 628 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: 629 { 630 if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED"); 631 boolean isUnexpectedDisconnect = false; 632 synchronized(mConnection) { 633 mBluetooth = null; 634 if (mUnbinding) { 635 mUnbinding = false; 636 } else { 637 isUnexpectedDisconnect = true; 638 } 639 } 640 if (!mConnection.isGetNameAddressOnly()) { 641 if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: Calling onBluetoothSerivceDown callbacks"); 642 try { 643 for (IBluetoothManagerCallback callback : mCallbacks) { 644 callback.onBluetoothServiceDown(); 645 } 646 } catch (RemoteException e) { 647 Log.e(TAG, "", e); 648 } 649 } 650 } 651 break; 652 case MESSAGE_TIMEOUT_UNBIND: 653 { 654 Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND"); 655 synchronized(mConnection) { 656 mUnbinding = false; 657 } 658 } 659 break; 660 } 661 } 662 }; 663} 664