Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdce0b98 authored by Matthew Xie's avatar Matthew Xie Committed by Android (Google) Code Review
Browse files

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
parent fe19f123
Loading
Loading
Loading
Loading
+158 −168
Original line number Original line Diff line number Diff line
@@ -41,8 +41,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {


    private static final int MESSAGE_ENABLE = 1;
    private static final int MESSAGE_ENABLE = 1;
    private static final int MESSAGE_DISABLE = 2;
    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_REGISTER_ADAPTER = 20;
    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
    private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
@@ -57,6 +55,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    private static final int MAX_SAVE_RETRIES=3;
    private static final int MAX_SAVE_RETRIES=3;


    private final Context mContext;
    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 mAddress;
    private String mName;
    private String mName;
    private final ContentResolver mContentResolver;
    private final ContentResolver mContentResolver;
@@ -99,13 +100,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                }
                }
            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
            } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
                if (isAirplaneModeOn()) {
                if (isAirplaneModeOn()) {
                    Message msg = mHandler.obtainMessage(MESSAGE_AIRPLANE_MODE_ON);
                        // disable without persisting the setting
                    msg.arg1=0;
                        handleDisable(false);
                    mHandler.sendMessage(msg);
                } else {
                } else {
                    Message msg = mHandler.obtainMessage(MESSAGE_AIRPLANE_MODE_OFF);
                    if (isBluetoothPersistedStateOn()) {
                    msg.arg1=0;
                        // enable without persisting the setting
                    mHandler.sendMessage(msg);
                        handleEnable(false);
                    }
                }
                }
            }
            }
        }
        }
@@ -256,20 +257,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
        return false;
        return false;
    }
    }


    private boolean isConnected() {
        return mBluetooth != null;
    }

    public void getNameAndAddress() {
    public void getNameAndAddress() {
        if (DBG) {
        if (DBG) {
            Log.d(TAG,"getNameAndAddress(): mBluetooth = " +
            Log.d(TAG,"getNameAndAddress(): mBluetooth = " + mBluetooth +
                (mBluetooth==null?"null":mBluetooth) +
                  " mBinding = " + mBinding);
                " mBinding = " + mBinding +
                " isConnected = " + isConnected());
        }
        }
        synchronized(mConnection) {
        synchronized(mConnection) {
            if (mBinding) return;
            if (mBinding) return;
            if (!isConnected()) mBinding = true;
            if (mConnection == null) mBinding = true;
        }
        }
        Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
        Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
        mHandler.sendMessage(msg);
        mHandler.sendMessage(msg);
@@ -279,19 +274,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH ADMIN permission");
                                                "Need BLUETOOTH ADMIN permission");
        if (DBG) {
        if (DBG) {
            Log.d(TAG,"enable():  mBluetooth =" +
            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
                    (mBluetooth==null?"null":mBluetooth) +
                    " mBinding = " + mBinding);
                    " mBinding = " + mBinding +
                    " isConnected = " + isConnected());
        }
        }


        synchronized(mConnection) {
        synchronized(mConnection) {
            //if (mBluetooth != null) return false;
            if (mBinding) {
            if (mBinding) {
                Log.w(TAG,"enable(): binding in progress. Returning..");
                Log.w(TAG,"enable(): binding in progress. Returning..");
                return true;
                return true;
            }
            }
            if (!isConnected()) mBinding = true;
            if (mConnection == null) mBinding = true;
        }
        }


        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
        Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
@@ -304,10 +296,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
                                                "Need BLUETOOTH ADMIN permissicacheNameAndAddresson");
        if (DBG) {
        if (DBG) {
            Log.d(TAG,"disable(): mBluetooth = " +
            Log.d(TAG,"disable(): mBluetooth = " + mBluetooth +
                (mBluetooth==null?"null":mBluetooth) +
                " mBinding = " + mBinding);
                " mBinding = " + mBinding +
        }
                " isConnected = " + isConnected());}


        synchronized(mConnection) {
        synchronized(mConnection) {
             if (mBluetooth == null) return false;
             if (mBluetooth == null) return false;
@@ -320,16 +311,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub {


    public void unbindAndFinish() {
    public void unbindAndFinish() {
        if (DBG) {
        if (DBG) {
            Log.d(TAG,"unbindAndFinish(): " +
            Log.d(TAG,"unbindAndFinish(): " + mBluetooth +
                (mBluetooth==null?"null":mBluetooth) +
                " mBinding = " + mBinding);
                " mBinding = " + mBinding +
                " isConnected = " + isConnected());
        }
        }


        synchronized (mConnection) {
        synchronized (mConnection) {
            if (mUnbinding) return;
            if (mUnbinding) return;
            mUnbinding = true;
            mUnbinding = true;
            if (isConnected()) {
            if (mConnection != null) {
                if (!mConnection.isGetNameAddressOnly()) {
                if (!mConnection.isGetNameAddressOnly()) {
                    //Unregister callback object
                    //Unregister callback object
                    try {
                    try {
@@ -392,6 +381,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                }
                }
            }
            }
        }
        }
        // mAddress is accessed from outside.
        // It is alright without a lock. Here, bluetooth is off, no other thread is
        // changing mAddress
        return mAddress;
        return mAddress;
    }
    }


@@ -407,6 +399,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                }
                }
            }
            }
        }
        }
        // mName is accessed from outside.
        // It alright without a lock. Here, bluetooth is off, no other thread is
        // changing mName
        return mName;
        return mName;
    }
    }


@@ -446,9 +441,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            switch (msg.what) {
            switch (msg.what) {
                case MESSAGE_GET_NAME_AND_ADDRESS: {
                case MESSAGE_GET_NAME_AND_ADDRESS: {
                    if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS");
                    if (DBG) Log.d(TAG,"MESSAGE_GET_NAME_AND_ADDRESS");
                    if (mBluetooth == null) {
                    synchronized(mConnection) {
                        //Start bind request
                        //Start bind request
                        if (!isConnected()) {
                        if (mBluetooth == null) {
                            if (DBG) Log.d(TAG, "Binding to service to get name and address");
                            if (DBG) Log.d(TAG, "Binding to service to get name and address");
                            mConnection.setGetNameAddressOnly(true);
                            mConnection.setGetNameAddressOnly(true);
                            //Start bind timeout and bind
                            //Start bind timeout and bind
@@ -461,14 +456,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                                Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
                                Log.e(TAG, "fail to bind to: " + IBluetooth.class.getName());
                            }
                            }
                        }
                        }
                    } else {
                        else {
                            Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
                            Message saveMsg= mHandler.obtainMessage(MESSAGE_SAVE_NAME_AND_ADDRESS);
                            mHandler.sendMessage(saveMsg);
                            mHandler.sendMessage(saveMsg);
                        }
                        }
                    }
                    }
                    break;
                    break;
                }
                case MESSAGE_SAVE_NAME_AND_ADDRESS: {
                case MESSAGE_SAVE_NAME_AND_ADDRESS: {
                    if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
                    if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS");
                    synchronized(mConnection) {
                        if (mBluetooth != null) {
                        if (mBluetooth != null) {
                            String name =  null;
                            String name =  null;
                            String address = null;
                            String address = null;
@@ -498,84 +495,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                        }
                        }
                    }
                    }
                    break;
                    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) {
                    if (DBG) {
                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth +
                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
                            " isConnected = " + isConnected());
                    }
                    boolean persist = (msg.arg1 == 1);
                    if (persist) {
                        persistBluetoothSetting(true);
                    }

                    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);
                    }
                    }


                    }
                    handleEnable(msg.arg1 == 1);
                    // 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
                }
                    break;
                    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 {
                case MESSAGE_DISABLE:
                            if(!mBluetooth.disable()) {
                    handleDisable(msg.arg1 == 1);
                                Log.e(TAG,"IBluetooth.disable() returned false");
                            }
                        } catch (RemoteException e) {
                            Log.e(TAG,"Unable to call disable()",e);
                        }
                    }
                    break;
                    break;

                case MESSAGE_REGISTER_ADAPTER:
                case MESSAGE_REGISTER_ADAPTER:
                {
                {
                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
@@ -588,20 +520,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
                    boolean removed = mCallbacks.unregister(callback);
                    boolean removed = mCallbacks.unregister(callback);
                    Log.d(TAG,"Removed callback: " +  (callback == null? "null": callback)  +":" + removed);
                    Log.d(TAG,"Removed callback: " +  (callback == null? "null": callback)  +":" + removed);
                }
                    break;
                    break;
                }
                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
                case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK:
                {
                {
                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
                    mStateChangeCallbacks.register(callback);
                    mStateChangeCallbacks.register(callback);
                }
                    break;
                    break;
                }
                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
                case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK:
                {
                {
                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
                    IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj;
                    mStateChangeCallbacks.unregister(callback);
                    mStateChangeCallbacks.unregister(callback);
                }
                    break;
                    break;
                }
                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
                {
                {
                    if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
                    if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
@@ -613,7 +545,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                    synchronized(mConnection) {
                    synchronized(mConnection) {
                        mBinding = false;
                        mBinding = false;
                        mBluetooth = IBluetooth.Stub.asInterface(service);
                        mBluetooth = IBluetooth.Stub.asInterface(service);
                    }


                        if (mConnection.isGetNameAddressOnly()) {
                        if (mConnection.isGetNameAddressOnly()) {
                            //Request GET NAME AND ADDRESS
                            //Request GET NAME AND ADDRESS
@@ -650,14 +581,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                            Log.e(TAG,"Unable to call enable()",e);
                            Log.e(TAG,"Unable to call enable()",e);
                        }
                        }
                    }
                    }

                    break;
                    break;
                }
                case MESSAGE_TIMEOUT_BIND: {
                case MESSAGE_TIMEOUT_BIND: {
                    Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
                    Log.e(TAG, "MESSAGE_TIMEOUT_BIND");
                    synchronized(mConnection) {
                    synchronized(mConnection) {
                        mBinding = false;
                        mBinding = false;
                    }
                    }
                }
                    break;
                    break;
                }
                case MESSAGE_BLUETOOTH_STATE_CHANGE:
                case MESSAGE_BLUETOOTH_STATE_CHANGE:
                {
                {
                    int prevState = msg.arg1;
                    int prevState = msg.arg1;
@@ -684,23 +617,80 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                        if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
                        if (DBG) Log.d(TAG,"Bluetooth State Change Intent: " + prevState + " -> " + newState);
                        mContext.sendBroadcast(intent,BLUETOOTH_PERM);
                        mContext.sendBroadcast(intent,BLUETOOTH_PERM);
                    }
                    }
                }
                    break;
                    break;
                }
                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
                case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
                {
                {
                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
                    if (DBG) Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
                    sendBluetoothServiceDownCallback();
                    sendBluetoothServiceDownCallback();
                }
                    break;
                    break;
                }
                case MESSAGE_TIMEOUT_UNBIND:
                case MESSAGE_TIMEOUT_UNBIND:
                {
                {
                    Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
                    Log.e(TAG, "MESSAGE_TIMEOUT_UNBIND");
                    synchronized(mConnection) {
                    synchronized(mConnection) {
                        mUnbinding = false;
                        mUnbinding = false;
                    }
                    }
                }
                    break;
                    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);
                }
            }
        }
    }
}
}