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

Commit a33fbc77 authored by Zach Johnson's avatar Zach Johnson
Browse files

Restart BT when init flags change

Restarts immediately, a future patch will ensure we restart
at a non-interruptive time.

Bug: 156757711
Test: atest BluetoothInstrumentationTests
Tag: #feature
Change-Id: I8be87c4132cadb39342bee10188db672029ae150
parent 3465b01f
Loading
Loading
Loading
Loading
+112 −74
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
@@ -114,6 +115,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    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 DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300;

    private static final int MESSAGE_ENABLE = 1;
    private static final int MESSAGE_DISABLE = 2;
@@ -133,6 +135,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
    private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
    private static final int MESSAGE_RESTORE_USER_SETTING = 500;
    private static final int MESSAGE_INIT_FLAGS_CHANGED = 600;

    private static final int RESTORE_SETTING_TO_ON = 1;
    private static final int RESTORE_SETTING_TO_OFF = 0;
@@ -278,6 +281,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                }
            };

    private final DeviceConfig.OnPropertyChangedListener mDeviceConfigChangedListener =
            new DeviceConfig.OnPropertyChangedListener() {
                @Override
                public void onPropertyChanged(String namespace, String name, String value) {
                    if (!namespace.equals(DeviceConfig.NAMESPACE_BLUETOOTH)) {
                        return;
                    }
                    if (!name.startsWith("INIT_")) {
                        return;
                    }
                    mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
                    mHandler.sendEmptyMessageDelayed(
                            MESSAGE_INIT_FLAGS_CHANGED,
                            DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS);
                }
            };

    public boolean onFactoryReset() {
        // Wait for stable state if bluetooth is temporary state.
        int state = getState();
@@ -507,6 +527,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            Slog.w(TAG, "Unable to resolve SystemUI's UID.");
        }
        mSystemUiUid = systemUiUid;
        DeviceConfig.addOnPropertyChangedListener(
                DeviceConfig.NAMESPACE_BLUETOOTH,
                (Runnable r) -> r.run(),
                mDeviceConfigChangedListener);
    }

    /**
@@ -2148,6 +2172,50 @@ class BluetoothManagerService extends IBluetoothManager.Stub {

                    /* disable and enable BT when detect a user switch */
                    if (mBluetooth != null && isEnabled()) {
                        restartForReason(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH);
                    } else if (mBinding || mBluetooth != null) {
                        Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
                        userMsg.arg2 = 1 + msg.arg2;
                        // if user is switched when service is binding retry after a delay
                        mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
                        if (DBG) {
                            Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
                        }
                    }
                    break;
                }
                case MESSAGE_USER_UNLOCKED: {
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
                    }
                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);

                    if (mEnable && !mBinding && (mBluetooth == null)) {
                        // We should be connected, but we gave up for some
                        // reason; maybe the Bluetooth service wasn't encryption
                        // aware, so try binding again.
                        if (DBG) {
                            Slog.d(TAG, "Enabled but not bound; retrying after unlock");
                        }
                        handleEnable(mQuietEnable);
                    }
                    break;
                }
                case MESSAGE_INIT_FLAGS_CHANGED: {
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED");
                    }
                    mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
                    if (mBluetooth != null && isEnabled()) {
                        restartForReason(
                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED);
                    }
                    break;
                }
            }
        }

        private void restartForReason(int reason) {
            try {
                mBluetoothLock.readLock().lock();
                if (mBluetooth != null) {
@@ -2160,7 +2228,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            }

            if (mState == BluetoothAdapter.STATE_TURNING_OFF) {
                            // MESSAGE_USER_SWITCHED happened right after MESSAGE_ENABLE
                bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_OFF);
                mState = BluetoothAdapter.STATE_OFF;
            }
@@ -2169,7 +2236,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                mState = BluetoothAdapter.STATE_TURNING_ON;
            }

                        waitForState(Set.of(BluetoothAdapter.STATE_ON));
            waitForOnOff(true, false);

            if (mState == BluetoothAdapter.STATE_TURNING_ON) {
                bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
@@ -2177,15 +2244,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {

            unbindAllBluetoothProfileServices();
            // disable
                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
                                mContext.getPackageName(), false);
            addActiveLog(reason, mContext.getPackageName(), false);
            handleDisable();
            // Pbap service need receive STATE_TURNING_OFF intent to close
            bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
                    BluetoothAdapter.STATE_TURNING_OFF);

                        boolean didDisableTimeout =
                                !waitForState(Set.of(BluetoothAdapter.STATE_OFF));
            boolean didDisableTimeout = !waitForOnOff(false, true);

            bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
                    BluetoothAdapter.STATE_OFF);
@@ -2217,39 +2282,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
            mState = BluetoothAdapter.STATE_OFF;
            // enable
                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
                                mContext.getPackageName(), true);
            addActiveLog(reason, mContext.getPackageName(), true);
            // mEnable flag could have been reset on disableBLE. Reenable it.
            mEnable = true;
            handleEnable(mQuietEnable);
                    } else if (mBinding || mBluetooth != null) {
                        Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
                        userMsg.arg2 = 1 + msg.arg2;
                        // if user is switched when service is binding retry after a delay
                        mHandler.sendMessageDelayed(userMsg, USER_SWITCHED_TIME_MS);
                        if (DBG) {
                            Slog.d(TAG, "Retry MESSAGE_USER_SWITCHED " + userMsg.arg2);
                        }
                    }
                    break;
                }
                case MESSAGE_USER_UNLOCKED: {
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
                    }
                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);

                    if (mEnable && !mBinding && (mBluetooth == null)) {
                        // We should be connected, but we gave up for some
                        // reason; maybe the Bluetooth service wasn't encryption
                        // aware, so try binding again.
                        if (DBG) {
                            Slog.d(TAG, "Enabled but not bound; retrying after unlock");
                        }
                        handleEnable(mQuietEnable);
                    }
                }
            }
        }
    }

@@ -2711,6 +2747,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                return "RESTORE_USER_SETTING";
            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET:
                return "FACTORY_RESET";
            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED:
                return "INIT_FLAGS_CHANGED";
            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
            default: return "UNKNOWN[" + reason + "]";
        }