blob: 3e985e2fa9f81693f432b1ac754b18952a80d0f6 [file] [log] [blame]
fredc0f420372012-04-12 00:02:00 -07001/*
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;
12
13import android.content.BroadcastReceiver;
14import android.content.ComponentName;
15import android.content.ContentResolver;
16import android.content.Context;
17import android.content.Intent;
18import android.content.IntentFilter;
19import android.content.ServiceConnection;
20import android.os.Handler;
21
22import android.os.IBinder;
23import android.os.Message;
24import android.os.RemoteException;
25import android.provider.Settings;
26import android.util.Log;
27import java.util.List;
28import java.util.ArrayList;
29
30class BluetoothManagerService extends IBluetoothManager.Stub {
31 private static final String TAG = "BluetoothManagerService";
32 private static final boolean DBG = true;
33
34 private static final boolean ALWAYS_SYNC_NAME_ADDRESS=true; //If true, always load name and address
35
36 private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
37 private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
38
39 private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
40 private static final String EXTRA_ACTION="action";
41
42 private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
43 private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
44
45 private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
46 private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
47
48 private static final int MESSAGE_ENABLE = 1;
49 private static final int MESSAGE_DISABLE = 2;
50 private static final int MESSAGE_REGISTER_ADAPTER = 3;
51 private static final int MESSAGE_UNREGISTER_ADAPTER = 4;
52 private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 5;
53 private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 6;
54 private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 11;
55 private static final int MESSAGE_BLUETOOTH_ON = 12;
56 private static final int MESSAGE_BLUETOOTH_OFF = 14;
57 private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 15;
58 private static final int MESSAGE_TIMEOUT_BIND =100;
59 private static final int MESSAGE_TIMEOUT_UNBIND =101;
60 private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
61 private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
62 private static final int MAX_SAVE_RETRIES=3;
63
64 private final Context mContext;
65 private String mAddress;
66 private String mName;
67 private ContentResolver mContentResolver;
68 private List<IBluetoothManagerCallback> mCallbacks;
69 private List<IBluetoothStateChangeCallback> mStateChangeCallbacks;
70
71 IntentFilter mFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
72 private BroadcastReceiver mReceiver = new BroadcastReceiver() {
73
74 @Override
75 public void onReceive(Context context, Intent intent) {
76 String action = intent.getAction();
77 if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
78 int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
79 if (state == BluetoothAdapter.STATE_OFF) {
80 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_OFF);
81 mHandler.sendMessage(msg);
82 } else if (state == BluetoothAdapter.STATE_ON) {
83 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_ON);
84 mHandler.sendMessage(msg);
85 }
86 } else if (BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) {
87 String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME);
88 Log.d(TAG, "Bluetooth Adapter name changed to " + newName);
89 if (newName != null) {
90 storeNameAndAddress(newName, null);
91 }
92 }
93 }
94 };
95
96 BluetoothManagerService(Context context) {
97 mContext = context;
98 mBluetooth = null;
99 mBinding = false;
100 mUnbinding = false;
101 mAddress = null;
102 mName = null;
103 mContentResolver = context.getContentResolver();
104 mCallbacks = new ArrayList<IBluetoothManagerCallback>();
105 mStateChangeCallbacks = new ArrayList<IBluetoothStateChangeCallback>();
106 mContext.registerReceiver(mReceiver, mFilter);
107
108 int airplaneModeOn = Settings.System.getInt(mContentResolver,
109 Settings.System.AIRPLANE_MODE_ON, 0);
110 int bluetoothOn = Settings.Secure.getInt(mContentResolver,
111 Settings.Secure.BLUETOOTH_ON, 0);
112 if (DBG) Log.d(TAG, "airplane mode: " + airplaneModeOn + " bluetoothOn: " + bluetoothOn);
113
114 loadStoredNameAndAddress();
115 if (airplaneModeOn == 0 && bluetoothOn!= 0) {
116 //Enable
117 if (DBG) Log.d(TAG, "Autoenabling Bluetooth.");
118 enable();
119 } else if (ALWAYS_SYNC_NAME_ADDRESS || !isNameAndAddressSet()) {
120 if (DBG) Log.d(TAG,"Retrieving name and address...");
121 getNameAndAddress();
122 }
123 }
124
125 private boolean isNameAndAddressSet() {
126 return mName !=null && mAddress!= null && mName.length()>0 && mAddress.length()>0;
127 }
128
129 private void loadStoredNameAndAddress() {
130 if (DBG) Log.d(TAG, "Loading stored name and address");
131 mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME);
132 mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS);
133 if (mName == null || mAddress == null) {
134 if (DBG) Log.d(TAG, "Name or address not cached...");
135 }
136 }
137
138 private void storeNameAndAddress(String name, String address) {
139 if (name != null) {
140 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name);
141 if (DBG) Log.d(TAG,"Stored name: " + Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_NAME));
142 mName = name;
143 }
144
145 if (address != null) {
146 Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address);
147 if (DBG) Log.d(TAG,"Stored address: " + Settings.Secure.getString(mContentResolver,SECURE_SETTINGS_BLUETOOTH_ADDRESS));
148 mAddress=address;
149 }
150 }
151
152 public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
153 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
154 "Need BLUETOOTH permission");
155 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
156 msg.obj = callback;
157 mHandler.sendMessage(msg);
158 synchronized(mConnection) {
159 return mBluetooth;
160 }
161 }
162
163 public void unregisterAdapter(IBluetoothManagerCallback callback) {
164 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
165 "Need BLUETOOTH permission");
166 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
167 msg.obj = callback;
168 mHandler.sendMessage(msg);
169 }
170
171 public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
172 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
173 "Need BLUETOOTH permission");
174 Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_STATE_CHANGE_CALLBACK);
175 msg.obj = callback;
176 mHandler.sendMessage(msg);
177 }
178
179 public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
180 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
181 "Need BLUETOOTH permission");
182 Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK);
183 msg.obj = callback;
184 mHandler.sendMessage(msg);
185 }
186
187 public boolean isEnabled() {
188 synchronized(mConnection) {
189 try {
190 return (mBluetooth != null && mBluetooth.isEnabled());
191 } catch (RemoteException e) {
192 Log.e(TAG, "isEnabled()", e);
193 }
194 }
195 return false;
196 }
197
fredcf2458862012-04-16 15:18:27 -0700198 private boolean isConnected() {
199 return mBluetooth != null;
200 }
fredc0f420372012-04-12 00:02:00 -0700201 public void getNameAndAddress() {
fredcf2458862012-04-16 15:18:27 -0700202 if (DBG) {
203 Log.d(TAG,"getNameAndAddress() called");
204 Log.d(TAG,"mBluetooth = " + mBluetooth);
205 Log.d(TAG,"mBinding = "+ mBinding);
206 Log.d(TAG,"isConnected() = " + isConnected());
207 }
208
fredc0f420372012-04-12 00:02:00 -0700209 synchronized(mConnection) {
210 if (mBinding) return ;
fredcf2458862012-04-16 15:18:27 -0700211 if (!isConnected()) mBinding = true;
fredc0f420372012-04-12 00:02:00 -0700212 }
213 Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
214 mHandler.sendMessage(msg);
215 }
216
217 public boolean enable() {
218 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
219 "Need BLUETOOTH ADMIN permission");
fredcf2458862012-04-16 15:18:27 -0700220 if (DBG) {
221 Log.d(TAG,"enable() called");
222 Log.d(TAG,"mBluetooth = " + mBluetooth);
223 Log.d(TAG,"mBinding = "+ mBinding);
224 Log.d(TAG,"isConnected = " + isConnected());
225 }
226
fredc0f420372012-04-12 00:02:00 -0700227 synchronized(mConnection) {
228 //if (mBluetooth != null) return false; [fc] always allow an enable() to occur.
229 //If service is bound, we should not assume that bluetooth is enabled. What if
230 //Bluetooth never turned on?
231 if (mBinding) return true;
fredcf2458862012-04-16 15:18:27 -0700232 if (!isConnected()) mBinding = true;
233 Log.d(TAG,"enable(): setting mBinding to true" );
fredc0f420372012-04-12 00:02:00 -0700234 }
235 Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
236 //msg.obj = new Boolean(true);
237 mHandler.sendMessage(msg);
238 return true;
239 }
240
241 public boolean disable(boolean persist) {
242 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
243 "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
fredcf2458862012-04-16 15:18:27 -0700244 if (DBG) {
245 Log.d(TAG,"disable() called");
246 Log.d(TAG,"mBluetooth = " + mBluetooth);
247 Log.d(TAG,"mBinding = "+ mBinding);
248 Log.d(TAG,"isConnected() = " + isConnected());
249 }
250
fredc0f420372012-04-12 00:02:00 -0700251 synchronized(mConnection) {
252 if (mBluetooth == null) return false;
253 //if (mUnbinding) return true;
254 //mUnbinding = true;
255 }
256 Message msg = mHandler.obtainMessage(MESSAGE_DISABLE);
257 msg.obj = new Boolean(persist);
258 mHandler.sendMessage(msg);
259 return true;
260 }
261
262 public void unbindAndFinish(boolean sendStop) {
fredcf2458862012-04-16 15:18:27 -0700263 if (DBG) {
264 Log.d(TAG,"unbindAndFinish() called");
265 Log.d(TAG,"mBluetooth = " + mBluetooth);
266 Log.d(TAG,"mBinding = "+ mBinding);
267 Log.d(TAG,"isConnected = " + isConnected());
268 }
269
fredc0f420372012-04-12 00:02:00 -0700270 synchronized (mConnection) {
271 if (mUnbinding) return;
272 mUnbinding = true;
fredcf2458862012-04-16 15:18:27 -0700273 if (isConnected()) {
fredc0f420372012-04-12 00:02:00 -0700274 if (sendStop) {
275 if (DBG) Log.d(TAG,"Sending stop request.");
276 Intent i = new Intent(IBluetooth.class.getName());
277 i.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED);
278 i.putExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.STATE_OFF);
279 mContext.startService(i);
280 }
281 if (DBG) Log.d(TAG, "Sending unbind request.");
282 mContext.unbindService(mConnection);
283 mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED));
fredcf2458862012-04-16 15:18:27 -0700284 } else {
285 mUnbinding=false;
fredc0f420372012-04-12 00:02:00 -0700286 }
287 }
288 }
289
290 public String getAddress() {
291 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
292 "Need BLUETOOTH ADMIN permission");
293 return mAddress;
294 }
295 public String getName() {
296 mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
297 "Need BLUETOOTH ADMIN permission");
298 return mName;
299 }
300
301 private IBluetooth mBluetooth;
302 private boolean mBinding;
303 private boolean mUnbinding;
fredc0f420372012-04-12 00:02:00 -0700304
305 private class BluetoothServiceConnection implements ServiceConnection {
306
307 private boolean mGetNameAddressOnly;
308
309 public void setGetNameAddressOnly(boolean getOnly) {
310 mGetNameAddressOnly = getOnly;
311 }
312
313 public boolean isGetNameAddressOnly() {
314 return mGetNameAddressOnly;
315 }
316
317 public void onServiceConnected(ComponentName className, IBinder service) {
318 if (DBG) Log.d(TAG, "Proxy object connected");
319 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
320 msg.obj = service;
321 mHandler.sendMessage(msg);
322 }
323
324 public void onServiceDisconnected(ComponentName className) {
325 if (DBG) Log.d(TAG, "Proxy object disconnected");
326 // Called if we unexpected disconnected.
327 Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
328 mHandler.sendMessage(msg);
329 }
330 }
331
332 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
333
334 private final Handler mHandler = new Handler() {
335 @Override
336 public void handleMessage(Message msg) {
337 if (DBG) Log.d (TAG, "Message: " + msg.what);
338
339 switch (msg.what) {
340 case MESSAGE_GET_NAME_AND_ADDRESS: {
341 if (mBluetooth == null) {
342 //Start bind request
fredcf2458862012-04-16 15:18:27 -0700343 if (!isConnected()) {
fredc0f420372012-04-12 00:02:00 -0700344 if (DBG) Log.d(TAG, "Binding to service to get name and address");
345 mConnection.setGetNameAddressOnly(true);
346 //Start bind timeout and bind
347 Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
348 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
349 Intent i = new Intent(IBluetooth.class.getName());
350 if (!mContext.bindService(i, mConnection,
351 Context.BIND_AUTO_CREATE)) {
352 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
353 Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
354 }
355 }
356 } else {
357 Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
358 mHandler.sendMessage(saveMsg);
359 }
360 }
361 break;
362 case MESSAGE_SAVE_NAME_AND_ADDRESS: {
363 if (mBluetooth != null) {
364 String name = null;
365 String address = null;
366 try {
367 name = mBluetooth.getName();
368 address = mBluetooth.getAddress();
369 } catch (RemoteException re) {
370 Log.e(TAG,"",re);
371 }
372
373 if (name != null && address != null) {
374 storeNameAndAddress(name,address);
375 unbindAndFinish(false);
376 } else {
377 if (msg.arg1 < MAX_SAVE_RETRIES) {
378 Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
379 retryMsg.arg1= 1+msg.arg1;
380 if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1);
381 mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
382 } else {
383 Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
384 unbindAndFinish(false);
385 }
386 }
387 }
388 }
389 break;
390 case MESSAGE_ENABLE: {
fredcf2458862012-04-16 15:18:27 -0700391 if (DBG) {
392 Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
393 Log.d(TAG, "MESSAGE_ENABLE: isConnected = " + isConnected());
394 }
fredc0f420372012-04-12 00:02:00 -0700395 if (mBluetooth == null) {
396 //Start bind request
fredcf2458862012-04-16 15:18:27 -0700397 if (!isConnected()) {
fredc0f420372012-04-12 00:02:00 -0700398 //Start bind timeout and bind
399 Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
400 mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
401 Intent i = new Intent(IBluetooth.class.getName());
402 i.putExtra(EXTRA_ACTION, ACTION_SERVICE_STATE_CHANGED);
403 i.putExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.STATE_ON);
404 mContext.startService(i);
405 mConnection.setGetNameAddressOnly(false);
406 if (!mContext.bindService(i, mConnection,
407 Context.BIND_AUTO_CREATE)) {
408 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
409 Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
410 }
411 }
412 } else {
413 //Check if name and address is loaded if not get it first.
414 if (ALWAYS_SYNC_NAME_ADDRESS || !isNameAndAddressSet()) {
415 try {
416 if (DBG) Log.d(TAG,"Bluetooth Proxy available: getting name and address prior to enable.");
417 storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress());
418 } catch (RemoteException e) {Log.e(TAG, "", e);};
419 }
420 try {
fredcf2458862012-04-16 15:18:27 -0700421 boolean success = mBluetooth.enable();
422 Log.d(TAG, "Called mBluetooth.enable() returned " + success);
fredc0f420372012-04-12 00:02:00 -0700423 } catch (RemoteException e) {Log.e(TAG, "", e);};
424 }
425 // TODO(BT) what if service failed to start:
426 // [fc] fixed: watch for bind timeout and handle accordingly
427 // TODO(BT) persist the setting depending on argument
428 // [fc]: let AdapterServiceHandle
429 }
430 break;
431 case MESSAGE_DISABLE:
432 if (mBluetooth != null ) {
433 boolean persist = (Boolean)msg.obj;
434 try {
435 mConnection.setGetNameAddressOnly(false);
436 mBluetooth.disable(persist);
437 //We will only unbind once we are sure that Bluetooth is OFFMESSAGE_TIMEOUT_UNBIND
438 //mContext.unbindService(mConnection);
439 } catch (RemoteException e) {
440 Log.e(TAG, "Error disabling Bluetooth", e);
441 }
442 }
443
444 // TODO(BT) what if service failed to stop:
445 // [fc] fixed: watch for disable event and unbind accordingly
446 // TODO(BT) persist the setting depending on argument
447 // [fc]: let AdapterServiceHandle
448
449 break;
450 case MESSAGE_REGISTER_ADAPTER:
451 {
452 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
453 mCallbacks.add(callback);
454 }
455 break;
456 case MESSAGE_UNREGISTER_ADAPTER:
457 {
458 IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
459 mCallbacks.remove(callback);
460 }
461 break;
462 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
463 {
464 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
465 mStateChangeCallbacks.add(callback);
466 }
467 break;
468 case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
469 {
470 IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
471 mStateChangeCallbacks.remove(callback);
472 }
473 break;
474 case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
475 {
476 if (DBG) Log.d(TAG,"Bluetooth service connnected!");
477 //Remove timeout
478 mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
479
480 IBinder service = (IBinder) msg.obj;
481 synchronized(mConnection) {
fredc0f420372012-04-12 00:02:00 -0700482 mBinding = false;
483 mBluetooth = IBluetooth.Stub.asInterface(service);
484 }
485
486 if (mConnection.isGetNameAddressOnly()) {
487 //Request GET NAME AND ADDRESS
488 Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
489 mHandler.sendMessage(getMsg);
490 return;
491 }
492
493 //Otherwise do the enable
494 if (DBG) Log.d(TAG,"Requesting Bluetooth enable...");
495 try {
496 for (IBluetoothManagerCallback callback : mCallbacks) {
497 callback.onBluetoothServiceUp(mBluetooth);
498 }
499 } catch (RemoteException e) {
500 Log.e(TAG, "", e);
501 }
502
503 //Request Enable
504 Message enableMsg = mHandler.obtainMessage(MESSAGE_ENABLE);
505 //enableMsg.obj = new Boolean(false);
506 mHandler.sendMessage(enableMsg);
507 }
508 break;
509 case MESSAGE_TIMEOUT_BIND:
510 {
511 Log.e(TAG, "Timeout while trying to bind to Bluetooth Service");
512 synchronized(mConnection) {
513 mBinding = false;
514 }
515 }
516 break;
517
518 case MESSAGE_BLUETOOTH_ON:
519 {
520 if (DBG) Log.d(TAG, "Bluetooth is on!!!");
521 try {
522 for (IBluetoothStateChangeCallback callback : mStateChangeCallbacks) {
523 callback.onBluetoothStateChange(true);
524 }
525 } catch (RemoteException e) {
526 Log.e(TAG, "", e);
527 }
528 }
529 break;
530
531 case MESSAGE_BLUETOOTH_OFF:
532 {
533 if (DBG) Log.d(TAG, "Bluetooth is off. Unbinding...");
534
535 try {
536 for (IBluetoothStateChangeCallback callback : mStateChangeCallbacks) {
537 callback.onBluetoothStateChange(false);
538 }
539 } catch (RemoteException e) {
540 Log.e(TAG, "", e);
541 }
542 unbindAndFinish(true);
543 }
544 case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
545 {
546 boolean isUnexpectedDisconnect = false;
547 synchronized(mConnection) {
548 mBluetooth = null;
fredc0f420372012-04-12 00:02:00 -0700549 if (mUnbinding) {
550 mUnbinding = false;
551 } else {
552 isUnexpectedDisconnect = true;
553 }
554 }
555 if (!isUnexpectedDisconnect &&!mConnection.isGetNameAddressOnly()) {
556 if (DBG) Log.d(TAG,"Service finished unbinding. Calling callbacks...");
557 try {
558 for (IBluetoothManagerCallback callback : mCallbacks) {
559 callback.onBluetoothServiceDown();
560 }
561 } catch (RemoteException e) {
562 Log.e(TAG, "", e);
563 }
564 }
565 }
566 break;
567 case MESSAGE_TIMEOUT_UNBIND:
568 {
569 Log.e(TAG, "Timeout while trying to unbind to Bluetooth Service");
570 synchronized(mConnection) {
571 mUnbinding = false;
572 }
573 }
574 break;
575 }
576 }
577 };
578}