Loading packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +20 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } Loading @@ -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 = ""; Loading Loading @@ -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); } Loading packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt +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 Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -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, Loading Loading @@ -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)) } Loading Loading
packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +20 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } Loading @@ -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 = ""; Loading Loading @@ -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); } Loading
packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt +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 Loading @@ -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 Loading Loading @@ -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( Loading Loading @@ -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, Loading Loading @@ -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)) } Loading