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

Commit 2acdd96a authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Set bluetooth to turning off when toggled

This will change the state immediately to turning off, and show it as
off on the tile, giving immediate feedback.

Test: manual, toggle tile.
Test: atest BluetoothTileTest
Flag: com.android.systemui.qs_ui_refactor_compose_fragment
Bug: 396372299

Change-Id: I4d2f3f47c976a3de9b78f60cc2053e65bc8c8035
parent ae8da20d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy

    private static final long DEFAULT_STALE_TIMEOUT = 10 * DateUtils.MINUTE_IN_MILLIS;
    protected static final Object ARG_SHOW_TRANSIENT_ENABLING = new Object();
    protected static final Object ARG_SHOW_TRANSIENT_DISABLING = new Object();

    private static final int READY_STATE_NOT_READY = 0;
    private static final int READY_STATE_READYING = 1;
+20 −6
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import com.android.systemui.plugins.qs.TileDetailsViewModel;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QsEventLogger;
import com.android.systemui.qs.flags.QsInCompose;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.res.R;
@@ -196,11 +197,18 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
    protected void handleUpdateState(BooleanState state, Object arg) {
        checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_BLUETOOTH);
        final boolean transientEnabling = arg == ARG_SHOW_TRANSIENT_ENABLING;
        final boolean enabled = transientEnabling || mController.isBluetoothEnabled();
        final boolean transientDisabling =
                QsInCompose.isEnabled() && arg == ARG_SHOW_TRANSIENT_DISABLING;
        final boolean enabled =
                transientEnabling || (mController.isBluetoothEnabled() && !transientDisabling);
        final boolean connected = mController.isBluetoothConnected();
        final boolean connecting = mController.isBluetoothConnecting();
        state.isTransient = transientEnabling || connecting ||
                mController.getBluetoothState() == BluetoothAdapter.STATE_TURNING_ON;
        state.isTransient = transientEnabling || transientDisabling || connecting
                || mController.getBluetoothState() == BluetoothAdapter.STATE_TURNING_ON;
        if (QsInCompose.isEnabled()) {
            state.isTransient = state.isTransient
                    || mController.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF;
        }
        if (!enabled || !connected || state.isTransient) {
            stopListeningToStaleDeviceMetadata();
        }
@@ -208,7 +216,8 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
        state.value = enabled;
        state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
        state.secondaryLabel = TextUtils.emptyIfNull(
                getSecondaryLabel(enabled, connecting, connected, state.isTransient));
                getSecondaryLabel(enabled, connecting, connected,
                        state.isTransient && transientEnabling));
        state.contentDescription = mContext.getString(
                R.string.accessibility_quick_settings_bluetooth);
        state.stateDescription = "";
@@ -241,8 +250,13 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {

    private void toggleBluetooth() {
        final boolean isEnabled = mState.value;
        if (QsInCompose.isEnabled()) {
            // Immediately enter transient enabling state when toggling bluetooth state.
            refreshState(isEnabled ? ARG_SHOW_TRANSIENT_DISABLING : ARG_SHOW_TRANSIENT_ENABLING);
        } else {
            // Immediately enter transient enabling state when turning bluetooth on.
        refreshState(isEnabled ? null : ARG_SHOW_TRANSIENT_ENABLING);
            refreshState(isEnabled ? ARG_SHOW_TRANSIENT_DISABLING : null);
        }
        mController.setBluetoothEnabled(!isEnabled);
    }

+42 −1
Original line number Diff line number Diff line
package com.android.systemui.qs.tiles

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.os.Handler
import android.os.Looper
@@ -8,11 +9,11 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.platform.test.flag.junit.FlagsParameterization.allCombinationsOf
import android.service.quicksettings.Tile
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.telephony.flags.Flags
import com.android.settingslib.Utils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.systemui.SysuiTestCase
@@ -82,6 +83,7 @@ class BluetoothTileTest(flags: FlagsParameterization) : SysuiTestCase() {
        testableLooper = TestableLooper.get(this)

        whenever(qsHost.context).thenReturn(mContext)
        whenever(bluetoothController.canConfigBluetooth()).thenReturn(true)

        tile =
            FakeBluetoothTile(
@@ -257,6 +259,38 @@ class BluetoothTileTest(flags: FlagsParameterization) : SysuiTestCase() {
            .removeOnMetadataChangedListener(eq(cachedDevice), any())
    }

    @Test
    @EnableFlags(QSComposeFragment.FLAG_NAME)
    fun disableBluetooth_transientTurningOff() {
        enableBluetooth()
        tile.refreshState()
        testableLooper.processAllMessages()

        tile.handleSecondaryClick(null)
        testableLooper.processAllMessages()

        val state = tile.state

        assertThat(state.state).isEqualTo(Tile.STATE_INACTIVE)
        assertThat(state.isTransient).isTrue()
        assertThat(state.icon).isEqualTo(createExpectedIcon(R.drawable.qs_bluetooth_icon_off))
    }

    @Test
    @EnableFlags(QSComposeFragment.FLAG_NAME)
    fun turningOffState() {
        setBluetoothTurningOff()

        tile.refreshState()
        testableLooper.processAllMessages()

        val state = tile.state

        assertThat(state.state).isEqualTo(Tile.STATE_INACTIVE)
        assertThat(state.isTransient).isTrue()
        assertThat(state.icon).isEqualTo(createExpectedIcon(R.drawable.qs_bluetooth_icon_off))
    }

    private class FakeBluetoothTile(
        qsHost: QSHost,
        uiEventLogger: QsEventLogger,
@@ -318,6 +352,13 @@ class BluetoothTileTest(flags: FlagsParameterization) : SysuiTestCase() {
        whenever(bluetoothController.isBluetoothConnecting).thenReturn(true)
    }

    fun setBluetoothTurningOff() {
        whenever(bluetoothController.isBluetoothConnected).thenReturn(false)
        whenever(bluetoothController.isBluetoothConnecting).thenReturn(false)
        whenever(bluetoothController.isBluetoothEnabled).thenReturn(false)
        whenever(bluetoothController.bluetoothState).thenReturn(BluetoothAdapter.STATE_TURNING_OFF)
    }

    fun addConnectedDevice(device: CachedBluetoothDevice) {
        whenever(bluetoothController.connectedDevices).thenReturn(listOf(device))
    }