Handle airplane mode messages in BroadcastReceiver, safe locking, etc
Handle airplane mode messages in BroadcastReceiver
Safe-lock the access of mBluetooth as a indication of binding state
break indent
Change-Id: Ib24ba0b1f5102c80e55e44b40a8dbf88bc2fad2e
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
index ac88a6a..cc9b9fa 100644
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -41,8 +41,6 @@
private static final int MESSAGE_ENABLE = 1;
private static final int MESSAGE_DISABLE = 2;
- private static final int MESSAGE_AIRPLANE_MODE_OFF=10;
- private static final int MESSAGE_AIRPLANE_MODE_ON=11;
private static final int MESSAGE_REGISTER_ADAPTER = 20;
private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
@@ -57,6 +55,9 @@
private static final int MAX_SAVE_RETRIES=3;
private final Context mContext;
+
+ // Locks are not provided for mName and mAddress.
+ // They are accessed in handler or broadcast receiver, same thread context.
private String mAddress;
private String mName;
private final ContentResolver mContentResolver;
@@ -99,13 +100,13 @@
}
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
if (isAirplaneModeOn()) {
- Message msg = mHandler.obtainMessage(MESSAGE_AIRPLANE_MODE_ON);
- msg.arg1=0;
- mHandler.sendMessage(msg);
+ // disable without persisting the setting
+ handleDisable(false);
} else {
- Message msg = mHandler.obtainMessage(MESSAGE_AIRPLANE_MODE_OFF);
- msg.arg1=0;
- mHandler.sendMessage(msg);
+ if (isBluetoothPersistedStateOn()) {
+ // enable without persisting the setting
+ handleEnable(false);
+ }
}
}
}
@@ -256,20 +257,14 @@
return false;
}
- private boolean isConnected() {
- return mBluetooth != null;
- }
-
public void getNameAndAddress() {
if (DBG) {
- Log.d(TAG,"getNameAndAddress(): mBluetooth = " +
- (mBluetooth==null?"null":mBluetooth) +
- " mBinding = " + mBinding +
- " isConnected = " + isConnected());
+ Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth +
+ " mBinding = " + mBinding);
}
synchronized(mConnection) {
- if (mBinding) return ;
- if (!isConnected()) mBinding = true;
+ if (mBinding) return;
+ if (mConnection == null) mBinding = true;
}
Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(msg);
@@ -279,19 +274,16 @@
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
if (DBG) {
- Log.d(TAG,"enable(): mBluetooth =" +
- (mBluetooth==null?"null":mBluetooth) +
- " mBinding = " + mBinding +
- " isConnected = " + isConnected());
+ Log.d(TAG,"enable(): mBluetooth =" + mBluetooth +
+ " mBinding = " + mBinding);
}
synchronized(mConnection) {
- //if (mBluetooth != null) return false;
if (mBinding) {
Log.w(TAG,"enable(): binding in progress. Returning..");
return true;
}
- if (!isConnected()) mBinding = true;
+ if (mConnection == null) mBinding = true;
}
Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
@@ -304,10 +296,9 @@
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
if (DBG) {
- Log.d(TAG,"disable(): mBluetooth = " +
- (mBluetooth==null?"null":mBluetooth) +
- " mBinding = " + mBinding +
- " isConnected = " + isConnected());}
+ Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
+ " mBinding = " + mBinding);
+ }
synchronized(mConnection) {
if (mBluetooth == null) return false;
@@ -320,16 +311,14 @@
public void unbindAndFinish() {
if (DBG) {
- Log.d(TAG,"unbindAndFinish(): " +
- (mBluetooth==null?"null":mBluetooth) +
- " mBinding = " + mBinding +
- " isConnected = " + isConnected());
+ Log.d(TAG,"unbindAndFinish(): " + mBluetooth +
+ " mBinding = " + mBinding);
}
synchronized (mConnection) {
if (mUnbinding) return;
mUnbinding = true;
- if (isConnected()) {
+ if (mConnection != null) {
if (!mConnection.isGetNameAddressOnly()) {
//Unregister callback object
try {
@@ -392,6 +381,9 @@
}
}
}
+ // mAddress is accessed from outside.
+ // It is alright without a lock. Here, bluetooth is off, no other thread is
+ // changing mAddress
return mAddress;
}
@@ -407,6 +399,9 @@
}
}
}
+ // mName is accessed from outside.
+ // It alright without a lock. Here, bluetooth is off, no other thread is
+ // changing mName
return mName;
}
@@ -446,9 +441,9 @@
switch (msg.what) {
case MESSAGE_GET_NAME_AND_ADDRESS: {
if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS");
- if (mBluetooth == null) {
+ synchronized(mConnection) {
//Start bind request
- if (!isConnected()) {
+ if (mBluetooth == null) {
if (DBG) Log.d(TAG, "Binding to service to get name and address");
mConnection.setGetNameAddressOnly(true);
//Start bind timeout and bind
@@ -461,121 +456,58 @@
Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
}
}
- } else {
- Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
- mHandler.sendMessage(saveMsg);
+ else {
+ Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+ mHandler.sendMessage(saveMsg);
+ }
}
- }
break;
+ }
case MESSAGE_SAVE_NAME_AND_ADDRESS: {
if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
- if (mBluetooth != null) {
- String name = null;
- String address = null;
- try {
- name = mBluetooth.getName();
- address = mBluetooth.getAddress();
- } catch (RemoteException re) {
- Log.e(TAG,"",re);
- }
+ synchronized(mConnection) {
+ if (mBluetooth != null) {
+ String name = null;
+ String address = null;
+ try {
+ name = mBluetooth.getName();
+ address = mBluetooth.getAddress();
+ } catch (RemoteException re) {
+ Log.e(TAG,"",re);
+ }
- if (name != null && address != null) {
- storeNameAndAddress(name,address);
- sendBluetoothServiceDownCallback();
- unbindAndFinish();
- } else {
- if (msg.arg1 < MAX_SAVE_RETRIES) {
- Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
- retryMsg.arg1= 1+msg.arg1;
- if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1);
- mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
- } else {
- Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
+ if (name != null && address != null) {
+ storeNameAndAddress(name,address);
sendBluetoothServiceDownCallback();
unbindAndFinish();
+ } else {
+ if (msg.arg1 < MAX_SAVE_RETRIES) {
+ Message retryMsg = mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
+ retryMsg.arg1= 1+msg.arg1;
+ if (DBG) Log.d(TAG,"Retrying name/address remote retrieval and save.....Retry count =" + retryMsg.arg1);
+ mHandler.sendMessageDelayed(retryMsg, TIMEOUT_SAVE_MS);
+ } else {
+ Log.w(TAG,"Maximum name/address remote retrieval retry exceeded");
+ sendBluetoothServiceDownCallback();
+ unbindAndFinish();
+ }
}
}
}
- }
break;
- case MESSAGE_AIRPLANE_MODE_OFF: {
- if (DBG) Log.d(TAG,"MESSAGE_AIRPLANE_MODE_OFF");
- //Check if we should turn on bluetooth
- if (!isBluetoothPersistedStateOn()) {
- if (DBG)Log.d(TAG, "Bluetooth persisted state is off. Not turning on Bluetooth.");
- return;
- }
- //Fall through to MESSAGE_ENABLE
}
- case MESSAGE_ENABLE: {
+ case MESSAGE_ENABLE:
if (DBG) {
- Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth +
- " isConnected = " + isConnected());
- }
- boolean persist = (msg.arg1 == 1);
- if (persist) {
- persistBluetoothSetting(true);
+ Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
}
- if (mBluetooth == null) {
- //Start bind timeout and bind
- Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
- mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
- mConnection.setGetNameAddressOnly(false);
- Intent i = new Intent(IBluetooth.class.getName());
- if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE)) {
- mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
- Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
- }
- } else {
- //Check if name and address is loaded if not get it first.
- if (!isNameAndAddressSet()) {
- try {
- if (DBG) Log.d(TAG,"Getting and storing Bluetooth name and address prior to enable.");
- storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress());
- } catch (RemoteException e) {Log.e(TAG, "", e);};
- }
-
- //Enable bluetooth
- try {
- if(!mBluetooth.enable()) {
- Log.e(TAG,"IBluetooth.enable() returned false");
- }
- } catch (RemoteException e) {
- Log.e(TAG,"Unable to call enable()",e);
- }
-
- }
- // TODO(BT) what if service failed to start:
- // [fc] fixed: watch for bind timeout and handle accordingly
- // TODO(BT) persist the setting depending on argument
- // [fc]: let AdapterServiceHandle
- }
+ handleEnable(msg.arg1 == 1);
break;
- case MESSAGE_AIRPLANE_MODE_ON:
- if (DBG) {
- Log.d(TAG, "MESSAGE_AIRPLANE_MODE_ON: mBluetooth = " + mBluetooth +
- " isConnected = " + isConnected());
- //Fall through to MESSAGE_DISABLE
- }
+
case MESSAGE_DISABLE:
- if (mBluetooth != null ) {
- boolean persist = (1==msg.arg1);
- if (persist) {
- persistBluetoothSetting(false);
- }
- mConnection.setGetNameAddressOnly(false);
- if (DBG) Log.d(TAG,"Sending off request.");
-
- try {
- if(!mBluetooth.disable()) {
- Log.e(TAG,"IBluetooth.disable() returned false");
- }
- } catch (RemoteException e) {
- Log.e(TAG,"Unable to call disable()",e);
- }
- }
+ handleDisable(msg.arg1 == 1);
break;
+
case MESSAGE_REGISTER_ADAPTER:
{
IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
@@ -588,20 +520,20 @@
IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
boolean removed = mCallbacks.unregister(callback);
Log.d(TAG,"Removed callback: " + (callback == null? "null": callback) +":" + removed);
- }
break;
+ }
case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
{
IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
mStateChangeCallbacks.register(callback);
- }
break;
+ }
case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
{
IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
mStateChangeCallbacks.unregister(callback);
- }
break;
+ }
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
@@ -613,51 +545,52 @@
synchronized(mConnection) {
mBinding = false;
mBluetooth = IBluetooth.Stub.asInterface(service);
- }
- if (mConnection.isGetNameAddressOnly()) {
- //Request GET NAME AND ADDRESS
- Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
- mHandler.sendMessage(getMsg);
- return;
- }
+ if (mConnection.isGetNameAddressOnly()) {
+ //Request GET NAME AND ADDRESS
+ Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+ mHandler.sendMessage(getMsg);
+ return;
+ }
- //Register callback object
- try {
- mBluetooth.registerCallback(mBluetoothCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothCallback",re);
- }
-
- //Inform BluetoothAdapter instances that service is up
- int n = mCallbacks.beginBroadcast();
- Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
- for (int i=0; i <n;i++) {
+ //Register callback object
try {
- mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ mBluetooth.registerCallback(mBluetoothCallback);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Unable to register BluetoothCallback",re);
}
- }
- mCallbacks.finishBroadcast();
- //Do enable request
- try {
- if(!mBluetooth.enable()) {
- Log.e(TAG,"IBluetooth.enable() returned false");
+ //Inform BluetoothAdapter instances that service is up
+ int n = mCallbacks.beginBroadcast();
+ Log.d(TAG,"Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+ for (int i=0; i <n;i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ }
}
- } catch (RemoteException e) {
- Log.e(TAG,"Unable to call enable()",e);
+ mCallbacks.finishBroadcast();
+
+ //Do enable request
+ try {
+ if(!mBluetooth.enable()) {
+ Log.e(TAG,"IBluetooth.enable() returned false");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG,"Unable to call enable()",e);
+ }
}
- }
+
break;
+ }
case MESSAGE_TIMEOUT_BIND: {
Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
synchronized(mConnection) {
mBinding = false;
}
- }
break;
+ }
case MESSAGE_BLUETOOTH_STATE_CHANGE:
{
int prevState = msg.arg1;
@@ -684,23 +617,80 @@
if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
mContext.sendBroadcast(intent,BLUETOOTH_PERM);
}
- }
break;
+ }
case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
{
if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
sendBluetoothServiceDownCallback();
- }
break;
+ }
case MESSAGE_TIMEOUT_UNBIND:
{
Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
synchronized(mConnection) {
mUnbinding = false;
}
- }
break;
+ }
}
}
};
+
+ private void handleEnable(boolean persist) {
+ if (persist) {
+ persistBluetoothSetting(true);
+ }
+
+ synchronized(mConnection) {
+ if (mBluetooth == null) {
+ //Start bind timeout and bind
+ Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
+ mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
+ mConnection.setGetNameAddressOnly(false);
+ Intent i = new Intent(IBluetooth.class.getName());
+ if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE)) {
+ mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+ Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());
+ }
+ } else {
+ //Check if name and address is loaded if not get it first.
+ if (!isNameAndAddressSet()) {
+ try {
+ if (DBG) Log.d(TAG,"Getting and storing Bluetooth name and address prior to enable.");
+ storeNameAndAddress(mBluetooth.getName(),mBluetooth.getAddress());
+ } catch (RemoteException e) {Log.e(TAG, "", e);};
+ }
+
+ //Enable bluetooth
+ try {
+ if(!mBluetooth.enable()) {
+ Log.e(TAG,"IBluetooth.enable() returned false");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG,"Unable to call enable()",e);
+ }
+ }
+ }
+ }
+
+ private void handleDisable(boolean persist) {
+ synchronized(mConnection) {
+ if (mBluetooth != null ) {
+ if (persist) {
+ persistBluetoothSetting(false);
+ }
+ mConnection.setGetNameAddressOnly(false);
+ if (DBG) Log.d(TAG,"Sending off request.");
+
+ try {
+ if(!mBluetooth.disable()) {
+ Log.e(TAG,"IBluetooth.disable() returned false");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG,"Unable to call disable()",e);
+ }
+ }
+ }
+ }
}