From 4c048327254e049de61166df8495465a10917fda Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Thu, 11 Feb 2021 08:46:10 -0500 Subject: [PATCH] Controls Visibility Start to move controls visibility logic into the ControlsComponent, allowing multiple locations to ask about the state of controls. Bug: 179782498 Test: atest GlobalActionsDialog ControlsComponentTest DeviceControlsTileTest Change-Id: I09ce096c05e8b8826bd7baa479872cc7a2feaad6 --- .../controls/dagger/ControlsComponent.kt | 76 +++++++++++- .../globalactions/GlobalActionsDialog.java | 34 +++--- .../systemui/qs/tiles/DeviceControlsTile.kt | 5 +- .../phone/KeyguardBottomAreaView.java | 64 +++++----- .../controls/dagger/ControlsComponentTest.kt | 111 ++++++++++++++++-- .../GlobalActionsDialogTest.java | 11 +- .../qs/tiles/DeviceControlsTileTest.kt | 34 +++++- 7 files changed, 265 insertions(+), 70 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt index 38a82f8c9908c..36937d622b5b8 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt @@ -16,10 +16,19 @@ package com.android.systemui.controls.dagger +import android.content.ContentResolver +import android.content.Context +import android.database.ContentObserver +import android.provider.Settings import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.settings.UserTracker +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.settings.SecureSettings +import com.android.internal.widget.LockPatternUtils +import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT import dagger.Lazy import java.util.Optional import javax.inject.Inject @@ -28,15 +37,43 @@ import javax.inject.Inject * Pseudo-component to inject into classes outside `com.android.systemui.controls`. * * If `featureEnabled` is false, all the optionals should be empty. The controllers will only be - * instantiated if `featureEnabled` is true. + * instantiated if `featureEnabled` is true. Can also be queried for the availability of controls. */ @SysUISingleton class ControlsComponent @Inject constructor( @ControlsFeatureEnabled private val featureEnabled: Boolean, + private val context: Context, private val lazyControlsController: Lazy, private val lazyControlsUiController: Lazy, - private val lazyControlsListingController: Lazy + private val lazyControlsListingController: Lazy, + private val lockPatternUtils: LockPatternUtils, + private val keyguardStateController: KeyguardStateController, + private val userTracker: UserTracker, + private val secureSettings: SecureSettings ) { + + private val contentResolver: ContentResolver + get() = context.contentResolver + + private var canShowWhileLockedSetting = false + + val showWhileLockedObserver = object : ContentObserver(null) { + override fun onChange(selfChange: Boolean) { + updateShowWhileLocked() + } + } + + init { + if (featureEnabled) { + secureSettings.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), + false, /* notifyForDescendants */ + showWhileLockedObserver + ) + updateShowWhileLocked() + } + } + fun getControlsController(): Optional { return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty() } @@ -52,4 +89,37 @@ class ControlsComponent @Inject constructor( Optional.empty() } } -} \ No newline at end of file + + /** + * @return true if controls are feature-enabled and have available services to serve controls + */ + fun isEnabled() = featureEnabled && lazyControlsController.get().available + + /** + * Returns one of 3 states: + * * AVAILABLE - Controls can be made visible + * * AVAILABLE_AFTER_UNLOCK - Controls can be made visible only after device unlock + * * UNAVAILABLE - Controls are not enabled + */ + fun getVisibility(): Visibility { + if (!isEnabled()) return Visibility.UNAVAILABLE + if (lockPatternUtils.getStrongAuthForUser(userTracker.userHandle.identifier) + == STRONG_AUTH_REQUIRED_AFTER_BOOT) { + return Visibility.AVAILABLE_AFTER_UNLOCK + } + if (!canShowWhileLockedSetting && !keyguardStateController.isUnlocked()) { + return Visibility.AVAILABLE_AFTER_UNLOCK + } + + return Visibility.AVAILABLE + } + + private fun updateShowWhileLocked() { + canShowWhileLockedSetting = secureSettings.getInt( + Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 0) != 0 + } + + enum class Visibility { + AVAILABLE, AVAILABLE_AFTER_UNLOCK, UNAVAILABLE + } +} diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 8af45a5c0ef10..d85b10167697f 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -25,6 +25,8 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOM import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; +import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE; +import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING; import android.animation.Animator; @@ -250,6 +252,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private final IWindowManager mIWindowManager; private final Executor mBackgroundExecutor; private List mControlsServiceInfos = new ArrayList<>(); + private ControlsComponent mControlsComponent; private Optional mControlsControllerOptional; private final RingerModeTracker mRingerModeTracker; private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms @@ -338,6 +341,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mSysuiColorExtractor = colorExtractor; mStatusBarService = statusBarService; mNotificationShadeWindowController = notificationShadeWindowController; + mControlsComponent = controlsComponent; mControlsUiControllerOptional = controlsComponent.getControlsUiController(); mIWindowManager = iWindowManager; mBackgroundExecutor = backgroundExecutor; @@ -387,7 +391,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, if (mDialog.mWalletViewController != null) { mDialog.mWalletViewController.onDeviceLockStateChanged(!unlocked); } - if (!mDialog.isShowingControls() && shouldShowControls()) { + if (!mDialog.isShowingControls() + && mControlsComponent.getVisibility() == AVAILABLE) { mDialog.showControls(mControlsUiControllerOptional.get()); } if (unlocked) { @@ -397,14 +402,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } }); - if (controlsComponent.getControlsListingController().isPresent()) { - controlsComponent.getControlsListingController().get() + if (mControlsComponent.getControlsListingController().isPresent()) { + mControlsComponent.getControlsListingController().get() .addCallback(list -> { mControlsServiceInfos = list; // This callback may occur after the dialog has been shown. If so, add // controls into the already visible space or show the lock msg if needed. if (mDialog != null) { - if (!mDialog.isShowingControls() && shouldShowControls()) { + if (!mDialog.isShowingControls() + && mControlsComponent.getVisibility() == AVAILABLE) { mDialog.showControls(mControlsUiControllerOptional.get()); } else if (shouldShowLockMessage(mDialog)) { mDialog.showLockMessage(); @@ -704,7 +710,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mDepthController.setShowingHomeControls(true); ControlsUiController uiController = null; - if (mControlsUiControllerOptional.isPresent() && shouldShowControls()) { + if (mControlsComponent.getVisibility() == AVAILABLE) { uiController = mControlsUiControllerOptional.get(); } ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, mOverflowAdapter, @@ -2687,26 +2693,24 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, return isPanelDebugModeEnabled(context); } - private boolean shouldShowControls() { - boolean showOnLockScreen = mShowLockScreenCardsAndControls && mLockPatternUtils - .getStrongAuthForUser(getCurrentUser().id) != STRONG_AUTH_REQUIRED_AFTER_BOOT; - return controlsAvailable() - && (mKeyguardStateController.isUnlocked() || showOnLockScreen); - } - private boolean controlsAvailable() { return mDeviceProvisioned - && mControlsUiControllerOptional.isPresent() - && mControlsUiControllerOptional.get().getAvailable() + && mControlsComponent.isEnabled() && !mControlsServiceInfos.isEmpty(); } private boolean shouldShowLockMessage(ActionsDialog dialog) { + return mControlsComponent.getVisibility() == AVAILABLE_AFTER_UNLOCK + || isWalletAvailableAfterUnlock(dialog); + } + + // Temporary while we move items out of the power menu + private boolean isWalletAvailableAfterUnlock(ActionsDialog dialog) { boolean isLockedAfterBoot = mLockPatternUtils.getStrongAuthForUser(getCurrentUser().id) == STRONG_AUTH_REQUIRED_AFTER_BOOT; return !mKeyguardStateController.isUnlocked() && (!mShowLockScreenCardsAndControls || isLockedAfterBoot) - && (controlsAvailable() || dialog.isWalletViewAvailable()); + && dialog.isWalletViewAvailable(); } private void onPowerMenuLockScreenSettingsChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index 6176a5702dcff..41445917a0112 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -25,6 +25,7 @@ import com.android.internal.logging.MetricsLogger import com.android.systemui.R import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.dagger.ControlsComponent +import com.android.systemui.controls.dagger.ControlsComponent.Visibility.UNAVAILABLE import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsDialog import com.android.systemui.dagger.qualifiers.Background @@ -91,7 +92,7 @@ class DeviceControlsTile @Inject constructor( override fun isAvailable(): Boolean { return featureFlags.isKeyguardLayoutEnabled && controlsLockscreen && - controlsComponent.getControlsUiController().isPresent + controlsComponent.getVisibility() != UNAVAILABLE } override fun newTileState(): QSTile.State { @@ -154,4 +155,4 @@ class DeviceControlsTile @Inject constructor( override fun getTileLabel(): CharSequence { return mContext.getText(R.string.quick_controls_title) } -} \ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 2ce0a8776266e..986333ce5010c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK; @@ -183,6 +184,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private ControlsComponent mControlsComponent; private int mLockScreenMode; private BroadcastDispatcher mBroadcastDispatcher; + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; public KeyguardBottomAreaView(Context context) { this(context, null); @@ -295,7 +297,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); getContext().registerReceiverAsUser(mDevicePolicyReceiver, UserHandle.ALL, filter, null, null); - Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateMonitorCallback); + mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); + mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); mKeyguardStateController.addCallback(this); } @@ -307,7 +310,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mRightExtension.destroy(); mLeftExtension.destroy(); getContext().unregisterReceiver(mDevicePolicyReceiver); - Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mUpdateMonitorCallback); + mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); } private void initAccessibility() { @@ -410,12 +413,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private void updateLeftAffordanceIcon() { - if (mDozing) { - mAltLeftButton.setVisibility(GONE); - } else if (mAltLeftButton.getDrawable() != null) { - mAltLeftButton.setVisibility(VISIBLE); - } - if (!mShowLeftAffordance || mDozing) { mLeftAffordanceView.setVisibility(GONE); return; @@ -430,6 +427,14 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLeftAffordanceView.setContentDescription(state.contentDescription); } + private void updateControlsVisibility() { + if (mDozing || mControlsComponent.getVisibility() != AVAILABLE) { + mAltLeftButton.setVisibility(GONE); + } else { + mAltLeftButton.setVisibility(VISIBLE); + } + } + public boolean isLeftVoiceAssist() { return mLeftIsVoiceAssist; } @@ -769,6 +774,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL updateCameraVisibility(); updateLeftAffordanceIcon(); + updateControlsVisibility(); if (dozing) { mOverlayContainer.setVisibility(INVISIBLE); @@ -889,35 +895,27 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private void setupControls() { - if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) { + boolean inNewLayout = mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL; + boolean settingEnabled = Settings.Global.getInt(mContext.getContentResolver(), + "controls_lockscreen", 0) == 1; + if (!inNewLayout || !settingEnabled || !mControlsComponent.isEnabled()) { mAltLeftButton.setVisibility(View.GONE); - mAltLeftButton.setOnClickListener(null); return; } - if (Settings.Global.getInt(mContext.getContentResolver(), "controls_lockscreen", 0) == 0) { - return; - } - - if (mControlsComponent.getControlsListingController().isPresent()) { - mControlsComponent.getControlsListingController().get() - .addCallback(list -> { - if (!list.isEmpty()) { - mAltLeftButton.setImageDrawable(list.get(0).loadIcon()); - mAltLeftButton.setVisibility(View.VISIBLE); - mAltLeftButton.setOnClickListener((v) -> { - ControlsUiController ui = mControlsComponent - .getControlsUiController().get(); - mControlsDialog = new ControlsDialog(mContext, mBroadcastDispatcher) - .show(ui); - }); - - } else { - mAltLeftButton.setVisibility(View.GONE); - mAltLeftButton.setOnClickListener(null); - } - }); - } + mControlsComponent.getControlsListingController().get() + .addCallback(list -> { + if (!list.isEmpty()) { + mAltLeftButton.setImageDrawable(list.get(0).loadIcon()); + mAltLeftButton.setOnClickListener((v) -> { + ControlsUiController ui = mControlsComponent + .getControlsUiController().get(); + mControlsDialog = new ControlsDialog(mContext, mBroadcastDispatcher) + .show(ui); + }); + } + updateControlsVisibility(); + }); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt index 7fe6827931525..b8f91b8d47193 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt @@ -17,11 +17,18 @@ package com.android.systemui.controls.dagger import android.testing.AndroidTestingRunner +import android.provider.Settings import androidx.test.filters.SmallTest +import com.android.internal.widget.LockPatternUtils +import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED +import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT import com.android.systemui.SysuiTestCase import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.settings.UserTracker +import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.settings.SecureSettings import dagger.Lazy import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -29,7 +36,11 @@ import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Answers import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -42,20 +53,29 @@ class ControlsComponentTest : SysuiTestCase() { private lateinit var uiController: ControlsUiController @Mock private lateinit var listingController: ControlsListingController + @Mock + private lateinit var keyguardStateController: KeyguardStateController + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private lateinit var userTracker: UserTracker + @Mock + private lateinit var lockPatternUtils: LockPatternUtils + @Mock + private lateinit var secureSettings: SecureSettings + + companion object { + fun eq(value: T): T = Mockito.eq(value) ?: value + } @Before fun setUp() { MockitoAnnotations.initMocks(this) + + `when`(userTracker.userHandle.identifier).thenReturn(0) } @Test fun testFeatureEnabled() { - val component = ControlsComponent( - true, - Lazy { controller }, - Lazy { uiController }, - Lazy { listingController } - ) + val component = setupComponent(true) assertTrue(component.getControlsController().isPresent) assertEquals(controller, component.getControlsController().get()) @@ -67,15 +87,80 @@ class ControlsComponentTest : SysuiTestCase() { @Test fun testFeatureDisabled() { - val component = ControlsComponent( - false, - Lazy { controller }, - Lazy { uiController }, - Lazy { listingController } - ) + val component = setupComponent(false) assertFalse(component.getControlsController().isPresent) assertFalse(component.getControlsUiController().isPresent) assertFalse(component.getControlsListingController().isPresent) } -} \ No newline at end of file + + @Test + fun testFeatureDisabledVisibility() { + val component = setupComponent(false) + + assertEquals(ControlsComponent.Visibility.UNAVAILABLE, component.getVisibility()) + } + + @Test + fun testFeatureEnabledAfterBootVisibility() { + `when`(controller.available).thenReturn(true) + `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) + .thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT) + val component = setupComponent(true) + + assertEquals(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK, component.getVisibility()) + } + + @Test + fun testFeatureEnabledAndCannotShowOnLockScreenVisibility() { + `when`(controller.available).thenReturn(true) + `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) + .thenReturn(STRONG_AUTH_NOT_REQUIRED) + `when`(keyguardStateController.isUnlocked()).thenReturn(false) + `when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt())) + .thenReturn(0) + val component = setupComponent(true) + + assertEquals(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK, component.getVisibility()) + } + + @Test + fun testFeatureEnabledAndCanShowOnLockScreenVisibility() { + `when`(controller.available).thenReturn(true) + `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) + .thenReturn(STRONG_AUTH_NOT_REQUIRED) + `when`(keyguardStateController.isUnlocked()).thenReturn(false) + `when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt())) + .thenReturn(1) + val component = setupComponent(true) + + assertEquals(ControlsComponent.Visibility.AVAILABLE, component.getVisibility()) + } + + @Test + fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() { + `when`(secureSettings.getInt(eq(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT), anyInt())) + .thenReturn(0) + `when`(controller.available).thenReturn(true) + `when`(lockPatternUtils.getStrongAuthForUser(anyInt())) + .thenReturn(STRONG_AUTH_NOT_REQUIRED) + `when`(keyguardStateController.isUnlocked()).thenReturn(true) + val component = setupComponent(true) + + assertEquals(ControlsComponent.Visibility.AVAILABLE, component.getVisibility()) + } + + private fun setupComponent(enabled: Boolean): ControlsComponent { + return ControlsComponent( + enabled, + mContext, + Lazy { controller }, + Lazy { uiController }, + Lazy { listingController }, + lockPatternUtils, + keyguardStateController, + userTracker, + secureSettings + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java index 78ee5936fe0bb..1062fae52e7a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java @@ -74,12 +74,14 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.GlobalActions; import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.settings.UserContextProvider; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.RingerModeLiveData; import com.android.systemui.util.RingerModeTracker; +import com.android.systemui.util.settings.SecureSettings; import org.junit.Before; import org.junit.Test; @@ -135,6 +137,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase { @Mock GlobalActionsPanelPlugin.PanelViewController mWalletController; @Mock private Handler mHandler; @Mock private UserContextProvider mUserContextProvider; + @Mock private UserTracker mUserTracker; + @Mock private SecureSettings mSecureSettings; private ControlsComponent mControlsComponent; private TestableLooper mTestableLooper; @@ -149,9 +153,14 @@ public class GlobalActionsDialogTest extends SysuiTestCase { when(mUserContextProvider.getUserContext()).thenReturn(mContext); mControlsComponent = new ControlsComponent( true, + mContext, () -> mControlsController, () -> mControlsUiController, - () -> mControlsListingController + () -> mControlsListingController, + mLockPatternUtils, + mKeyguardStateController, + mUserTracker, + mSecureSettings ); mGlobalActionsDialog = new GlobalActionsDialog(mContext, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt index b7b967866d473..d3dbe2bf7d2bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger +import com.android.internal.widget.LockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.controller.ControlsController @@ -36,15 +37,19 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.FeatureFlags +import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.GlobalSettings +import com.android.systemui.util.settings.SecureSettings import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Answers import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock @@ -91,6 +96,15 @@ class DeviceControlsTileTest : SysuiTestCase() { private lateinit var testableLooper: TestableLooper private lateinit var tile: DeviceControlsTile + @Mock + private lateinit var keyguardStateController: KeyguardStateController + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private lateinit var userTracker: UserTracker + @Mock + private lateinit var lockPatternUtils: LockPatternUtils + @Mock + private lateinit var secureSettings: SecureSettings + @Before fun setUp() { MockitoAnnotations.initMocks(this) @@ -101,9 +115,14 @@ class DeviceControlsTileTest : SysuiTestCase() { controlsComponent = ControlsComponent( true, + mContext, { controlsController }, { controlsUiController }, - { controlsListingController } + { controlsListingController }, + lockPatternUtils, + keyguardStateController, + userTracker, + secureSettings ) globalSettings = FakeSettings() @@ -111,16 +130,20 @@ class DeviceControlsTileTest : SysuiTestCase() { globalSettings.putInt(DeviceControlsTile.SETTINGS_FLAG, 1) `when`(featureFlags.isKeyguardLayoutEnabled).thenReturn(true) + `when`(userTracker.userHandle.identifier).thenReturn(0) + tile = createTile() } @Test fun testAvailable() { + `when`(controlsController.available).thenReturn(true) assertThat(tile.isAvailable).isTrue() } @Test fun testNotAvailableFeature() { + `when`(controlsController.available).thenReturn(true) `when`(featureFlags.isKeyguardLayoutEnabled).thenReturn(false) assertThat(tile.isAvailable).isFalse() @@ -130,9 +153,14 @@ class DeviceControlsTileTest : SysuiTestCase() { fun testNotAvailableControls() { controlsComponent = ControlsComponent( false, + mContext, { controlsController }, { controlsUiController }, - { controlsListingController } + { controlsListingController }, + lockPatternUtils, + keyguardStateController, + userTracker, + secureSettings ) tile = createTile() @@ -264,4 +292,4 @@ class DeviceControlsTileTest : SysuiTestCase() { globalSettings ) } -} \ No newline at end of file +}