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

Commit ef2b72fd authored by Ugo Yu's avatar Ugo Yu
Browse files

Sequentially handle enable and disable

* Replace thread sleeps in MESSAGE_ENABLE and MESSAGE_DISABLE to delay
  messages. To make sure we do not block the state change process while
  waiting for a state change callback.
* Prevent handling enable or disable at the same time by deferring the
  the request when we are enabling or disabling Bluetooth.

Bug: 128569058
Test: Manual
Change-Id: I2301ba22b6c10fcea71e3b66eea3ea0a0d7f0475
Merged-In: I2301ba22b6c10fcea71e3b66eea3ea0a0d7f0475
parent 7b97603a
Loading
Loading
Loading
Loading
+116 −11
Original line number Original line Diff line number Diff line
@@ -106,9 +106,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    private static final int USER_SWITCHED_TIME_MS = 200;
    private static final int USER_SWITCHED_TIME_MS = 200;
    // Delay for the addProxy function in msec
    // Delay for the addProxy function in msec
    private static final int ADD_PROXY_DELAY_MS = 100;
    private static final int ADD_PROXY_DELAY_MS = 100;
    // Delay for retrying enable and disable in msec
    private static final int ENABLE_DISABLE_DELAY_MS = 300;


    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_HANDLE_ENABLE_DELAYED = 3;
    private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4;
    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;
@@ -130,6 +134,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    private static final int RESTORE_SETTING_TO_OFF = 0;
    private static final int RESTORE_SETTING_TO_OFF = 0;


    private static final int MAX_ERROR_RESTART_RETRIES = 6;
    private static final int MAX_ERROR_RESTART_RETRIES = 6;
    private static final int MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES = 10;


    // Bluetooth persisted setting is off
    // Bluetooth persisted setting is off
    private static final int BLUETOOTH_OFF = 0;
    private static final int BLUETOOTH_OFF = 0;
@@ -160,6 +165,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock mBluetoothLock = new ReentrantReadWriteLock();
    private boolean mBinding;
    private boolean mBinding;
    private boolean mUnbinding;
    private boolean mUnbinding;
    private int mWaitForEnableRetry;
    private int mWaitForDisableRetry;


    private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
    private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;


@@ -1597,8 +1604,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                    break;
                    break;


                case MESSAGE_ENABLE:
                case MESSAGE_ENABLE:
                    int quietEnable = msg.arg1;
                    if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
                            || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
                        // We are handling enable or disable right now, wait for it.
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE,
                                quietEnable, 0), ENABLE_DISABLE_DELAY_MS);
                        break;
                    }

                    if (DBG) {
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
                        Slog.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth = "
                                + mBluetooth);
                    }
                    }
                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                    mEnable = true;
                    mEnable = true;
@@ -1621,7 +1638,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                        mBluetoothLock.readLock().unlock();
                        mBluetoothLock.readLock().unlock();
                    }
                    }


                    mQuietEnable = (msg.arg1 == 1);
                    mQuietEnable = (quietEnable == 1);
                    if (mBluetooth == null) {
                    if (mBluetooth == null) {
                        handleEnable(mQuietEnable);
                        handleEnable(mQuietEnable);
                    } else {
                    } else {
@@ -1630,7 +1647,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                        // the previous Bluetooth process has exited. The
                        // the previous Bluetooth process has exited. The
                        // waiting period has three components:
                        // waiting period has three components:
                        // (a) Wait until the local state is STATE_OFF. This
                        // (a) Wait until the local state is STATE_OFF. This
                        //     is accomplished by "waitForOnOff(false, true)".
                        //     is accomplished by sending delay a message
                        //     MESSAGE_HANDLE_ENABLE_DELAYED
                        // (b) Wait until the STATE_OFF state is updated to
                        // (b) Wait until the STATE_OFF state is updated to
                        //     all components.
                        //     all components.
                        // (c) Wait until the Bluetooth process exits, and
                        // (c) Wait until the Bluetooth process exits, and
@@ -1640,28 +1658,108 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                        // message. The delay time is backed off if Bluetooth
                        // message. The delay time is backed off if Bluetooth
                        // continuously failed to turn on itself.
                        // continuously failed to turn on itself.
                        //
                        //
                        waitForOnOff(false, true);
                        mWaitForEnableRetry = 0;
                        Message restartMsg =
                        Message enableDelayedMsg =
                                mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                                mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
                        mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
                        mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
                    }
                    }
                    break;
                    break;


                case MESSAGE_DISABLE:
                case MESSAGE_DISABLE:
                    if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding
                            || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
                        // We are handling enable or disable right now, wait for it.
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE),
                                ENABLE_DISABLE_DELAY_MS);
                        break;
                    }

                    if (DBG) {
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth);
                        Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth
                                + ", mBinding = " + mBinding);
                    }
                    }
                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);

                    if (mEnable && mBluetooth != null) {
                    if (mEnable && mBluetooth != null) {
                        waitForOnOff(true, false);
                        mWaitForDisableRetry = 0;
                        Message disableDelayedMsg =
                                mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0);
                        mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
                    } else {
                        mEnable = false;
                        mEnable = false;
                        handleDisable();
                        handleDisable();
                        waitForOnOff(false, false);
                    }
                    break;

                case MESSAGE_HANDLE_ENABLE_DELAYED: {
                    // The Bluetooth is turning off, wait for STATE_OFF
                    if (mState != BluetoothAdapter.STATE_OFF) {
                        if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
                            mWaitForEnableRetry++;
                            Message enableDelayedMsg =
                                    mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
                            mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
                            break;
                        } else {
                        } else {
                            Slog.e(TAG, "Wait for STATE_OFF timeout");
                        }
                    }
                    // Either state is changed to STATE_OFF or reaches the maximum retry, we
                    // should move forward to the next step.
                    mWaitForEnableRetry = 0;
                    Message restartMsg =
                            mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                    mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());
                    Slog.d(TAG, "Handle enable is finished");
                    break;
                }

                case MESSAGE_HANDLE_DISABLE_DELAYED: {
                    boolean disabling = (msg.arg1 == 1);
                    Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling);
                    if (!disabling) {
                        // The Bluetooth is turning on, wait for STATE_ON
                        if (mState != BluetoothAdapter.STATE_ON) {
                            if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
                                mWaitForDisableRetry++;
                                Message disableDelayedMsg = mHandler.obtainMessage(
                                        MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0);
                                mHandler.sendMessageDelayed(disableDelayedMsg,
                                        ENABLE_DISABLE_DELAY_MS);
                                break;
                            } else {
                                Slog.e(TAG, "Wait for STATE_ON timeout");
                            }
                        }
                        // Either state is changed to STATE_ON or reaches the maximum retry, we
                        // should move forward to the next step.
                        mWaitForDisableRetry = 0;
                        mEnable = false;
                        mEnable = false;
                        handleDisable();
                        handleDisable();
                        // Wait for state exiting STATE_ON
                        Message disableDelayedMsg =
                                mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
                        mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
                    } else {
                        // The Bluetooth is turning off, wait for exiting STATE_ON
                        if (mState == BluetoothAdapter.STATE_ON) {
                            if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {
                                mWaitForDisableRetry++;
                                Message disableDelayedMsg = mHandler.obtainMessage(
                                        MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
                                mHandler.sendMessageDelayed(disableDelayedMsg,
                                        ENABLE_DISABLE_DELAY_MS);
                                break;
                            } else {
                                Slog.e(TAG, "Wait for exiting STATE_ON timeout");
                            }
                        }
                        // Either state is exited from STATE_ON or reaches the maximum retry, we
                        // should move forward to the next step.
                        Slog.d(TAG, "Handle disable is finished");
                    }
                    }
                    break;
                    break;
                }


                case MESSAGE_RESTORE_USER_SETTING:
                case MESSAGE_RESTORE_USER_SETTING:
                    if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
                    if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
@@ -2031,6 +2129,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
        try {
        try {
            mBluetoothLock.writeLock().lock();
            mBluetoothLock.writeLock().lock();
            if ((mBluetooth == null) && (!mBinding)) {
            if ((mBluetooth == null) && (!mBinding)) {
                Slog.d(TAG, "binding Bluetooth service");
                //Start bind timeout and bind
                //Start bind timeout and bind
                Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
                Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
                mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
                mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
@@ -2418,6 +2517,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                writer.println("  " + app.getPackageName());
                writer.println("  " + app.getPackageName());
            }
            }


            writer.println("\nBluetoothManagerService:");
            writer.println("  mEnable:" + mEnable);
            writer.println("  mQuietEnable:" + mQuietEnable);
            writer.println("  mEnableExternal:" + mEnableExternal);
            writer.println("  mQuietEnableExternal:" + mQuietEnableExternal);

            writer.println("");
            writer.println("");
            writer.flush();
            writer.flush();
            if (args.length == 0) {
            if (args.length == 0) {