From e18cccbad203b7961dd7e8cc19ed9bd577b2afd3 Mon Sep 17 00:00:00 2001 From: Caitlin Shkuratov Date: Wed, 31 Aug 2022 20:03:38 +0000 Subject: [PATCH] [Status Bar] Disable the keyguard status bar when we get the DISABLE_SYSTEM_INFO or DISABLE2_SYSTEM_ICONS flags. Fixes: 240590557 Test: manual: CTS Verifier tests > Device Owner Tests > LockTasks UI > Enable keyguard. Turn screen off then turn screen on and verify the status bar in keyguard doesn't display. Test: manual: Verify keyguard status bar typically displays when not in the CTS verifier test case Test: DisableStateTrackerTest Test: KeyguardStatusBarViewControllerTest Change-Id: I4d19a168c295abee1ddfdf61452343dafa54cfc2 --- .../disableflags/DisableStateTracker.kt | 72 ++++++ .../KeyguardStatusBarViewController.java | 32 ++- .../disableflags/DisableStateTrackerTest.kt | 213 ++++++++++++++++++ .../KeyguardStatusBarViewControllerTest.java | 96 ++++++++ 4 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt new file mode 100644 index 0000000000000..562f58576ddcc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableStateTracker.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.statusbar.disableflags + +import com.android.systemui.statusbar.CommandQueue + +/** + * Tracks the relevant DISABLE_* flags provided in [mask1] and [mask2] and sets [isDisabled] based + * on those masks. [callback] will be notified whenever [isDisabled] changes. + * + * Users are responsible for adding and removing this tracker from [CommandQueue] callbacks. + */ +class DisableStateTracker( + private val mask1: Int, + private val mask2: Int, + private val callback: Callback, +) : CommandQueue.Callbacks { + /** + * True if any of the bits in [mask1] or [mask2] are on for the current disable flags, and false + * otherwise. + */ + var isDisabled = false + private set(value) { + if (field == value) return + field = value + callback.onDisabledChanged() + } + + private var displayId: Int? = null + + /** Start tracking the disable flags and updating [isDisabled] accordingly. */ + fun startTracking(commandQueue: CommandQueue, displayId: Int) { + // A view will only have its displayId once it's attached to a window, so we can only + // provide the displayId when we start tracking. + this.displayId = displayId + commandQueue.addCallback(this) + } + + /** + * Stop tracking the disable flags. + * + * [isDisabled] will stay at the same value until we start tracking again. + */ + fun stopTracking(commandQueue: CommandQueue) { + this.displayId = null + commandQueue.removeCallback(this) + } + + override fun disable(displayId: Int, state1: Int, state2: Int, animate: Boolean) { + if (this.displayId == null || displayId != this.displayId) { + return + } + isDisabled = state1 and mask1 != 0 || state2 and mask2 != 0 + } + + /** Callback triggered whenever the value of [isDisabled] changes. */ + fun interface Callback { + fun onDisabledChanged() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index f06b346780daa..ce2c9c2446962 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -16,6 +16,9 @@ package com.android.systemui.statusbar.phone; +import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; +import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO; + import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import android.animation.Animator; @@ -43,8 +46,10 @@ import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shade.NotificationPanelViewController; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.disableflags.DisableStateTracker; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.AnimatableProperty; @@ -108,6 +113,7 @@ public class KeyguardStatusBarViewController extends ViewController mBlockedIcons = new ArrayList<>(); private final int mNotificationsHeaderCollideDistance; @@ -269,6 +278,7 @@ public class KeyguardStatusBarViewController extends ViewController mView.setKeyguardUserAvatarEnabled(!enabled)); mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r); + + mDisableStateTracker = new DisableStateTracker( + /* mask1= */ DISABLE_SYSTEM_INFO, + /* mask2= */ DISABLE2_SYSTEM_ICONS, + this::updateViewState + ); } @Override @@ -333,6 +350,7 @@ public class KeyguardStatusBarViewController extends ViewController isDisabled = true + underTest.disable( + DISPLAY_ID, + state1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION, + state2 = 0, + animate = false + ) + assertThat(underTest.isDisabled).isTrue() + + // Irrelevant flags from mask1 -> isDisabled = false + underTest.disable( + DISPLAY_ID, + state1 = DISABLE_NOTIFICATION_ICONS or DISABLE_NOTIFICATION_TICKER, + state2 = 0, + animate = false + ) + assertThat(underTest.isDisabled).isFalse() + + // All flags from mask1 & all flags from mask2 -> isDisabled = true + underTest.disable( + DISPLAY_ID, + state1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION, + state2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS, + animate = false + ) + assertThat(underTest.isDisabled).isTrue() + + // No flags -> isDisabled = false + underTest.disable(DISPLAY_ID, state1 = 0, state2 = 0, animate = false) + assertThat(underTest.isDisabled).isFalse() + + // 1 flag from mask1 & 1 flag from mask2 -> isDisabled = true + underTest.disable( + DISPLAY_ID, + state1 = DISABLE_NAVIGATION, + state2 = DISABLE2_SYSTEM_ICONS, + animate = false + ) + assertThat(underTest.isDisabled).isTrue() + } + + companion object { + private const val DISPLAY_ID = 3 + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java index 6cf1a12d94f08..ba5f5038c1d97 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java @@ -17,6 +17,9 @@ package com.android.systemui.statusbar.phone; +import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; +import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO; + import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; @@ -49,6 +52,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shade.NotificationPanelViewController; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserInfoTracker; @@ -118,6 +122,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { @Mock private StatusBarUserInfoTracker mStatusBarUserInfoTracker; @Mock private SecureSettings mSecureSettings; + @Mock private CommandQueue mCommandQueue; private TestNotificationPanelViewStateProvider mNotificationPanelViewStateProvider; private KeyguardStatusBarView mKeyguardStatusBarView; @@ -137,6 +142,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { mKeyguardStatusBarView = spy((KeyguardStatusBarView) LayoutInflater.from(mContext) .inflate(R.layout.keyguard_status_bar, null)); + when(mKeyguardStatusBarView.getDisplay()).thenReturn(mContext.getDisplay()); }); mController = createController(); @@ -165,6 +171,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { mStatusBarUserSwitcherController, mStatusBarUserInfoTracker, mSecureSettings, + mCommandQueue, mFakeExecutor ); } @@ -176,6 +183,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { verify(mConfigurationController).addCallback(any()); verify(mAnimationScheduler).addCallback(any()); verify(mUserInfoController).addCallback(any()); + verify(mCommandQueue).addCallback(any()); verify(mStatusBarIconController).addIconGroup(any()); verify(mUserManager).isUserSwitcherEnabled(anyBoolean()); } @@ -214,6 +222,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { verify(mConfigurationController).removeCallback(any()); verify(mAnimationScheduler).removeCallback(any()); verify(mUserInfoController).removeCallback(any()); + verify(mCommandQueue).removeCallback(any()); verify(mStatusBarIconController).removeIconGroup(any()); } @@ -279,6 +288,17 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(newVisibility); } + @Test + public void updateViewState_paramVisibleButIsDisabled_viewIsInvisible() { + mController.onViewAttached(); + setDisableSystemIcons(true); + + mController.updateViewState(1f, View.VISIBLE); + + // Since we're disabled, we stay invisible + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE); + } + @Test public void updateViewState_notKeyguardState_nothingUpdated() { mController.onViewAttached(); @@ -358,6 +378,50 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE); } + @Test + public void updateViewState_disableSystemInfoFalse_viewShown() { + mController.onViewAttached(); + updateStateToKeyguard(); + setDisableSystemInfo(false); + + mController.updateViewState(); + + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateViewState_disableSystemInfoTrue_viewHidden() { + mController.onViewAttached(); + updateStateToKeyguard(); + setDisableSystemInfo(true); + + mController.updateViewState(); + + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE); + } + + @Test + public void updateViewState_disableSystemIconsFalse_viewShown() { + mController.onViewAttached(); + updateStateToKeyguard(); + setDisableSystemIcons(false); + + mController.updateViewState(); + + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateViewState_disableSystemIconsTrue_viewHidden() { + mController.onViewAttached(); + updateStateToKeyguard(); + setDisableSystemIcons(true); + + mController.updateViewState(); + + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE); + } + @Test public void setAlpha_explicitAlpha_setsExplicitAlpha() { mController.onViewAttached(); @@ -485,6 +549,19 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { callback.onStateChanged(state); } + @Test + public void animateKeyguardStatusBarIn_isDisabled_viewStillHidden() { + mController.onViewAttached(); + updateStateToKeyguard(); + setDisableSystemInfo(true); + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE); + + mController.animateKeyguardStatusBarIn(); + + // Since we're disabled, we don't actually animate in and stay invisible + assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE); + } + /** * Calls {@link com.android.keyguard.KeyguardUpdateMonitorCallback#onFinishedGoingToSleep(int)} * to ensure values are updated properly. @@ -498,6 +575,25 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { callback.onFinishedGoingToSleep(0); } + private void setDisableSystemInfo(boolean disabled) { + CommandQueue.Callbacks callback = getCommandQueueCallback(); + int disabled1 = disabled ? DISABLE_SYSTEM_INFO : 0; + callback.disable(mContext.getDisplayId(), disabled1, 0, false); + } + + private void setDisableSystemIcons(boolean disabled) { + CommandQueue.Callbacks callback = getCommandQueueCallback(); + int disabled2 = disabled ? DISABLE2_SYSTEM_ICONS : 0; + callback.disable(mContext.getDisplayId(), 0, disabled2, false); + } + + private CommandQueue.Callbacks getCommandQueueCallback() { + ArgumentCaptor captor = + ArgumentCaptor.forClass(CommandQueue.Callbacks.class); + verify(mCommandQueue).addCallback(captor.capture()); + return captor.getValue(); + } + private static class TestNotificationPanelViewStateProvider implements NotificationPanelViewController.NotificationPanelViewStateProvider {