Hide views on lockscreen when wallpaper dream is active When dreaming, only keyguard clock is visible on lockscreen. Bug: b/285061111 Test: atest LockIconViewControllerWithCoroutinesTest Test: atest KeyguardClockSwitchControllerWithCoroutinesTest Test: atest KeyguardIndicationControllerWithCoroutinesTest Change-Id: Ic38ad5c8260bb4869508a2d7b27ecd39a72d341e Merged-In: Ic38ad5c8260bb4869508a2d7b27ecd39a72d341e
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 6c98376..16eb21d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -21,6 +21,8 @@ import static com.android.keyguard.KeyguardClockSwitch.LARGE; import static com.android.keyguard.KeyguardClockSwitch.SMALL; +import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; +import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.annotation.Nullable; import android.database.ContentObserver; @@ -33,12 +35,15 @@ import android.widget.LinearLayout; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.log.LogBuffer; import com.android.systemui.log.core.LogLevel; import com.android.systemui.log.dagger.KeyguardClockLog; @@ -58,6 +63,7 @@ import java.io.PrintWriter; import java.util.Locale; +import java.util.function.Consumer; import javax.inject.Inject; @@ -99,8 +105,20 @@ private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private boolean mOnlyClock = false; + private boolean mIsActiveDreamLockscreenHosted = false; + private FeatureFlags mFeatureFlags; + private KeyguardInteractor mKeyguardInteractor; private final DelayableExecutor mUiExecutor; private boolean mCanShowDoubleLineClock = true; + @VisibleForTesting + final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback = + (Boolean isLockscreenHosted) -> { + if (mIsActiveDreamLockscreenHosted == isLockscreenHosted) { + return; + } + mIsActiveDreamLockscreenHosted = isLockscreenHosted; + updateKeyguardStatusAreaVisibility(); + }; private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) { @Override public void onChange(boolean change) { @@ -137,7 +155,9 @@ @Main DelayableExecutor uiExecutor, DumpManager dumpManager, ClockEventController clockEventController, - @KeyguardClockLog LogBuffer logBuffer) { + @KeyguardClockLog LogBuffer logBuffer, + KeyguardInteractor keyguardInteractor, + FeatureFlags featureFlags) { super(keyguardClockSwitch); mStatusBarStateController = statusBarStateController; mClockRegistry = clockRegistry; @@ -151,6 +171,8 @@ mClockEventController = clockEventController; mLogBuffer = logBuffer; mView.setLogBuffer(mLogBuffer); + mFeatureFlags = featureFlags; + mKeyguardInteractor = keyguardInteractor; mClockChangedListener = new ClockRegistry.ClockChangeListener() { @Override @@ -191,6 +213,12 @@ mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks mDumpManager.registerDumpable(getClass().toString(), this); + + if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) { + mStatusArea = mView.findViewById(R.id.keyguard_status_area); + collectFlow(mStatusArea, mKeyguardInteractor.isActiveDreamLockscreenHosted(), + mIsActiveDreamLockscreenHostedCallback); + } } @Override @@ -524,6 +552,15 @@ } } + private void updateKeyguardStatusAreaVisibility() { + if (mStatusArea != null) { + mUiExecutor.execute(() -> { + mStatusArea.setVisibility( + mIsActiveDreamLockscreenHosted ? View.INVISIBLE : View.VISIBLE); + }); + } + } + /** * Sets the clipChildren property on relevant views, to allow the smartspace to draw out of * bounds during the unlock transition.
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 8ef6c2e..5459718 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -24,6 +24,7 @@ import static com.android.keyguard.LockIconView.ICON_UNLOCK; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1; +import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.content.res.Configuration; @@ -124,6 +125,7 @@ private int mActivePointerId = -1; private boolean mIsDozing; + private boolean mIsActiveDreamLockscreenHosted; private boolean mIsBouncerShowing; private boolean mRunningFPS; private boolean mCanDismissLockScreen; @@ -165,6 +167,13 @@ updateVisibility(); }; + @VisibleForTesting + final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback = + (Boolean isLockscreenHosted) -> { + mIsActiveDreamLockscreenHosted = isLockscreenHosted; + updateVisibility(); + }; + @Inject public LockIconViewController( @Nullable LockIconView view, @@ -224,6 +233,11 @@ mDozeTransitionCallback); collectFlow(mView, mKeyguardInteractor.isDozing(), mIsDozingCallback); } + + if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) { + collectFlow(mView, mKeyguardInteractor.isActiveDreamLockscreenHosted(), + mIsActiveDreamLockscreenHostedCallback); + } } @Override @@ -289,6 +303,11 @@ return; } + if (mIsKeyguardShowing && mIsActiveDreamLockscreenHosted) { + mView.setVisibility(View.INVISIBLE); + return; + } + boolean wasShowingFpIcon = mUdfpsEnrolled && !mShowUnlockIcon && !mShowLockIcon && !mShowAodUnlockedIcon && !mShowAodLockIcon; mShowLockIcon = !mCanDismissLockScreen && isLockScreen() @@ -436,6 +455,7 @@ pw.println(" mInterpolatedDarkAmount: " + mInterpolatedDarkAmount); pw.println(" mSensorTouchLocation: " + mSensorTouchLocation); pw.println(" mDefaultPaddingPx: " + mDefaultPaddingPx); + pw.println(" mIsActiveDreamLockscreenHosted: " + mIsActiveDreamLockscreenHosted); if (mView != null) { mView.dump(pw, args);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 42ebaa3..73d8445 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -29,6 +29,7 @@ import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; @@ -43,6 +44,7 @@ import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON; import static com.android.systemui.log.core.LogLevel.ERROR; import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY; +import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.app.AlarmManager; import android.app.admin.DevicePolicyManager; @@ -96,6 +98,7 @@ import com.android.systemui.keyguard.KeyguardIndication; import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController; import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.util.IndicationHelper; import com.android.systemui.log.core.LogLevel; import com.android.systemui.plugins.FalsingManager; @@ -114,6 +117,7 @@ import java.text.NumberFormat; import java.util.HashSet; import java.util.Set; +import java.util.function.Consumer; import javax.inject.Inject; @@ -171,7 +175,7 @@ public KeyguardIndicationRotateTextViewController mRotateTextViewController; private BroadcastReceiver mBroadcastReceiver; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - + private KeyguardInteractor mKeyguardInteractor; private String mPersistentUnlockMessage; private String mAlignmentIndication; private CharSequence mTrustGrantedIndication; @@ -205,7 +209,17 @@ private KeyguardUpdateMonitorCallback mUpdateMonitorCallback; private boolean mDozing; + private boolean mIsActiveDreamLockscreenHosted; private final ScreenLifecycle mScreenLifecycle; + @VisibleForTesting + final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback = + (Boolean isLockscreenHosted) -> { + if (mIsActiveDreamLockscreenHosted == isLockscreenHosted) { + return; + } + mIsActiveDreamLockscreenHosted = isLockscreenHosted; + updateDeviceEntryIndication(false); + }; private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { @Override @@ -261,7 +275,8 @@ UserTracker userTracker, BouncerMessageInteractor bouncerMessageInteractor, FeatureFlags flags, - IndicationHelper indicationHelper + IndicationHelper indicationHelper, + KeyguardInteractor keyguardInteractor ) { mContext = context; mBroadcastDispatcher = broadcastDispatcher; @@ -289,6 +304,7 @@ mBouncerMessageInteractor = bouncerMessageInteractor; mFeatureFlags = flags; mIndicationHelper = indicationHelper; + mKeyguardInteractor = keyguardInteractor; mFaceAcquiredMessageDeferral = faceHelpMessageDeferral; mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>(); @@ -371,6 +387,10 @@ intentFilter.addAction(Intent.ACTION_USER_REMOVED); mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, intentFilter); } + if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) { + collectFlow(mIndicationArea, mKeyguardInteractor.isActiveDreamLockscreenHosted(), + mIsActiveDreamLockscreenHostedCallback); + } } /** @@ -878,6 +898,12 @@ return; } + // Device is dreaming and the dream is hosted in lockscreen + if (mIsActiveDreamLockscreenHosted) { + mIndicationArea.setVisibility(GONE); + return; + } + // A few places might need to hide the indication, so always start by making it visible mIndicationArea.setVisibility(VISIBLE); @@ -1069,6 +1095,7 @@ pw.println(" mBiometricMessageFollowUp: " + mBiometricMessageFollowUp); pw.println(" mBatteryLevel: " + mBatteryLevel); pw.println(" mBatteryPresent: " + mBatteryPresent); + pw.println(" mIsActiveDreamLockscreenHosted: " + mIsActiveDreamLockscreenHosted); pw.println(" AOD text: " + ( mTopIndicationView == null ? null : mTopIndicationView.getText())); pw.println(" computePowerIndication(): " + computePowerIndication());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java new file mode 100644 index 0000000..ac04bc4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
@@ -0,0 +1,210 @@ +/* + * Copyright (C) 2023 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.keyguard; + +import static android.view.View.INVISIBLE; + +import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR; +import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.res.Resources; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory; +import com.android.systemui.log.LogBuffer; +import com.android.systemui.plugins.ClockAnimations; +import com.android.systemui.plugins.ClockController; +import com.android.systemui.plugins.ClockEvents; +import com.android.systemui.plugins.ClockFaceConfig; +import com.android.systemui.plugins.ClockFaceController; +import com.android.systemui.plugins.ClockFaceEvents; +import com.android.systemui.plugins.ClockTickRate; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.clocks.AnimatableClockView; +import com.android.systemui.shared.clocks.ClockRegistry; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; +import com.android.systemui.statusbar.phone.NotificationIconAreaController; +import com.android.systemui.statusbar.phone.NotificationIconContainer; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.settings.SecureSettings; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class KeyguardClockSwitchControllerBaseTest extends SysuiTestCase { + + @Mock + protected KeyguardClockSwitch mView; + @Mock + protected StatusBarStateController mStatusBarStateController; + @Mock + protected ClockRegistry mClockRegistry; + @Mock + KeyguardSliceViewController mKeyguardSliceViewController; + @Mock + NotificationIconAreaController mNotificationIconAreaController; + @Mock + LockscreenSmartspaceController mSmartspaceController; + + @Mock + Resources mResources; + @Mock + KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + @Mock + protected ClockController mClockController; + @Mock + protected ClockFaceController mLargeClockController; + @Mock + protected ClockFaceController mSmallClockController; + @Mock + protected ClockAnimations mClockAnimations; + @Mock + protected ClockEvents mClockEvents; + @Mock + protected ClockFaceEvents mClockFaceEvents; + @Mock + DumpManager mDumpManager; + @Mock + ClockEventController mClockEventController; + + @Mock + protected NotificationIconContainer mNotificationIcons; + @Mock + protected AnimatableClockView mSmallClockView; + @Mock + protected AnimatableClockView mLargeClockView; + @Mock + protected FrameLayout mSmallClockFrame; + @Mock + protected FrameLayout mLargeClockFrame; + @Mock + protected SecureSettings mSecureSettings; + @Mock + protected LogBuffer mLogBuffer; + + protected final View mFakeDateView = (View) (new ViewGroup(mContext) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) {} + }); + protected final View mFakeWeatherView = new View(mContext); + protected final View mFakeSmartspaceView = new View(mContext); + + protected KeyguardClockSwitchController mController; + protected View mSliceView; + protected LinearLayout mStatusArea; + protected FakeExecutor mExecutor; + protected FakeFeatureFlags mFakeFeatureFlags; + @Captor protected ArgumentCaptor<View.OnAttachStateChangeListener> mAttachCaptor = + ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + when(mView.findViewById(R.id.left_aligned_notification_icon_container)) + .thenReturn(mNotificationIcons); + when(mNotificationIcons.getLayoutParams()).thenReturn( + mock(RelativeLayout.LayoutParams.class)); + when(mView.getContext()).thenReturn(getContext()); + when(mView.getResources()).thenReturn(mResources); + when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)) + .thenReturn(100); + when(mResources.getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin)) + .thenReturn(-200); + when(mResources.getInteger(R.integer.keyguard_date_weather_view_invisibility)) + .thenReturn(INVISIBLE); + + when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame); + when(mView.findViewById(R.id.lockscreen_clock_view)).thenReturn(mSmallClockFrame); + when(mSmallClockView.getContext()).thenReturn(getContext()); + when(mLargeClockView.getContext()).thenReturn(getContext()); + + when(mView.isAttachedToWindow()).thenReturn(true); + when(mSmartspaceController.buildAndConnectDateView(any())).thenReturn(mFakeDateView); + when(mSmartspaceController.buildAndConnectWeatherView(any())).thenReturn(mFakeWeatherView); + when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView); + mExecutor = new FakeExecutor(new FakeSystemClock()); + mFakeFeatureFlags = new FakeFeatureFlags(); + mFakeFeatureFlags.set(FACE_AUTH_REFACTOR, false); + mFakeFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false); + mController = new KeyguardClockSwitchController( + mView, + mStatusBarStateController, + mClockRegistry, + mKeyguardSliceViewController, + mNotificationIconAreaController, + mSmartspaceController, + mKeyguardUnlockAnimationController, + mSecureSettings, + mExecutor, + mDumpManager, + mClockEventController, + mLogBuffer, + KeyguardInteractorFactory.create(mFakeFeatureFlags).getKeyguardInteractor(), + mFakeFeatureFlags + ); + + when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); + when(mLargeClockController.getView()).thenReturn(mLargeClockView); + when(mSmallClockController.getView()).thenReturn(mSmallClockView); + when(mClockController.getLargeClock()).thenReturn(mLargeClockController); + when(mClockController.getSmallClock()).thenReturn(mSmallClockController); + when(mClockController.getEvents()).thenReturn(mClockEvents); + when(mSmallClockController.getEvents()).thenReturn(mClockFaceEvents); + when(mLargeClockController.getEvents()).thenReturn(mClockFaceEvents); + when(mLargeClockController.getAnimations()).thenReturn(mClockAnimations); + when(mSmallClockController.getAnimations()).thenReturn(mClockAnimations); + when(mClockRegistry.createCurrentClock()).thenReturn(mClockController); + when(mClockEventController.getClock()).thenReturn(mClockController); + when(mSmallClockController.getConfig()) + .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false)); + when(mLargeClockController.getConfig()) + .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false)); + + mSliceView = new View(getContext()); + when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); + mStatusArea = new LinearLayout(getContext()); + when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(mStatusArea); + } + + protected void init() { + mController.init(); + + verify(mView, atLeast(1)).addOnAttachStateChangeListener(mAttachCaptor.capture()); + mAttachCaptor.getValue().onViewAttachedToWindow(mView); + } +}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index 9e561ed..e64ef04 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -21,186 +21,33 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.res.Resources; import android.database.ContentObserver; import android.os.UserHandle; import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; import androidx.test.filters.SmallTest; -import com.android.systemui.R; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardUnlockAnimationController; -import com.android.systemui.log.LogBuffer; -import com.android.systemui.plugins.ClockAnimations; -import com.android.systemui.plugins.ClockController; -import com.android.systemui.plugins.ClockEvents; import com.android.systemui.plugins.ClockFaceConfig; -import com.android.systemui.plugins.ClockFaceController; -import com.android.systemui.plugins.ClockFaceEvents; import com.android.systemui.plugins.ClockTickRate; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.shared.clocks.AnimatableClockView; import com.android.systemui.shared.clocks.ClockRegistry; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; -import com.android.systemui.statusbar.phone.NotificationIconAreaController; -import com.android.systemui.statusbar.phone.NotificationIconContainer; -import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.settings.SecureSettings; -import com.android.systemui.util.time.FakeSystemClock; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.verification.VerificationMode; @SmallTest @RunWith(AndroidTestingRunner.class) -public class KeyguardClockSwitchControllerTest extends SysuiTestCase { - - @Mock - private KeyguardClockSwitch mView; - @Mock - private StatusBarStateController mStatusBarStateController; - @Mock - private ClockRegistry mClockRegistry; - @Mock - KeyguardSliceViewController mKeyguardSliceViewController; - @Mock - NotificationIconAreaController mNotificationIconAreaController; - @Mock - LockscreenSmartspaceController mSmartspaceController; - - @Mock - Resources mResources; - @Mock - KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; - @Mock - private ClockController mClockController; - @Mock - private ClockFaceController mLargeClockController; - @Mock - private ClockFaceController mSmallClockController; - @Mock - private ClockAnimations mClockAnimations; - @Mock - private ClockEvents mClockEvents; - @Mock - private ClockFaceEvents mClockFaceEvents; - @Mock - DumpManager mDumpManager; - @Mock - ClockEventController mClockEventController; - - @Mock - private NotificationIconContainer mNotificationIcons; - @Mock - private AnimatableClockView mSmallClockView; - @Mock - private AnimatableClockView mLargeClockView; - @Mock - private FrameLayout mSmallClockFrame; - @Mock - private FrameLayout mLargeClockFrame; - @Mock - private SecureSettings mSecureSettings; - @Mock - private LogBuffer mLogBuffer; - - private final View mFakeDateView = (View) (new ViewGroup(mContext) { - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) {} - }); - private final View mFakeWeatherView = new View(mContext); - private final View mFakeSmartspaceView = new View(mContext); - - private KeyguardClockSwitchController mController; - private View mSliceView; - private FakeExecutor mExecutor; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - - when(mView.findViewById(R.id.left_aligned_notification_icon_container)) - .thenReturn(mNotificationIcons); - when(mNotificationIcons.getLayoutParams()).thenReturn( - mock(RelativeLayout.LayoutParams.class)); - when(mView.getContext()).thenReturn(getContext()); - when(mView.getResources()).thenReturn(mResources); - when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)) - .thenReturn(100); - when(mResources.getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin)) - .thenReturn(-200); - when(mResources.getInteger(R.integer.keyguard_date_weather_view_invisibility)) - .thenReturn(View.INVISIBLE); - - when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame); - when(mView.findViewById(R.id.lockscreen_clock_view)).thenReturn(mSmallClockFrame); - when(mSmallClockView.getContext()).thenReturn(getContext()); - when(mLargeClockView.getContext()).thenReturn(getContext()); - - when(mView.isAttachedToWindow()).thenReturn(true); - when(mSmartspaceController.buildAndConnectDateView(any())).thenReturn(mFakeDateView); - when(mSmartspaceController.buildAndConnectWeatherView(any())).thenReturn(mFakeWeatherView); - when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView); - mExecutor = new FakeExecutor(new FakeSystemClock()); - mController = new KeyguardClockSwitchController( - mView, - mStatusBarStateController, - mClockRegistry, - mKeyguardSliceViewController, - mNotificationIconAreaController, - mSmartspaceController, - mKeyguardUnlockAnimationController, - mSecureSettings, - mExecutor, - mDumpManager, - mClockEventController, - mLogBuffer - ); - - when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); - when(mLargeClockController.getView()).thenReturn(mLargeClockView); - when(mSmallClockController.getView()).thenReturn(mSmallClockView); - when(mClockController.getLargeClock()).thenReturn(mLargeClockController); - when(mClockController.getSmallClock()).thenReturn(mSmallClockController); - when(mClockController.getEvents()).thenReturn(mClockEvents); - when(mSmallClockController.getEvents()).thenReturn(mClockFaceEvents); - when(mLargeClockController.getEvents()).thenReturn(mClockFaceEvents); - when(mLargeClockController.getAnimations()).thenReturn(mClockAnimations); - when(mSmallClockController.getAnimations()).thenReturn(mClockAnimations); - when(mClockRegistry.createCurrentClock()).thenReturn(mClockController); - when(mClockEventController.getClock()).thenReturn(mClockController); - when(mSmallClockController.getConfig()) - .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false)); - when(mLargeClockController.getConfig()) - .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false)); - - mSliceView = new View(getContext()); - when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); - when(mView.findViewById(R.id.keyguard_status_area)).thenReturn( - new LinearLayout(getContext())); - } - +public class KeyguardClockSwitchControllerTest extends KeyguardClockSwitchControllerBaseTest { @Test public void testInit_viewAlreadyAttached() { mController.init();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt new file mode 100644 index 0000000..9a1a4e2 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerWithCoroutinesTest.kt
@@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023 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.keyguard + +import android.testing.AndroidTestingRunner +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class KeyguardClockSwitchControllerWithCoroutinesTest : KeyguardClockSwitchControllerBaseTest() { + + @Test + fun testStatusAreaVisibility_onLockscreenHostedDreamStateChanged() = + runBlocking(IMMEDIATE) { + // GIVEN starting state for the keyguard clock and wallpaper dream enabled + mFakeFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, true) + init() + + // WHEN dreaming starts + mController.mIsActiveDreamLockscreenHostedCallback.accept( + true /* isActiveDreamLockscreenHosted */ + ) + + // THEN the status area is hidden + mExecutor.runAllReady() + assertEquals(View.INVISIBLE, mStatusArea.visibility) + + // WHEN dreaming stops + mController.mIsActiveDreamLockscreenHostedCallback.accept( + false /* isActiveDreamLockscreenHosted */ + ) + mExecutor.runAllReady() + + // THEN status area view is visible + assertEquals(View.VISIBLE, mStatusArea.visibility) + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java index 75106e7..956e0b81 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -19,6 +19,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1; import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR; +import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; import static com.android.systemui.flags.Flags.MIGRATE_LOCK_ICON; import static org.mockito.Mockito.any; @@ -147,6 +148,7 @@ mFeatureFlags = new FakeFeatureFlags(); mFeatureFlags.set(FACE_AUTH_REFACTOR, false); mFeatureFlags.set(MIGRATE_LOCK_ICON, false); + mFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false); mUnderTest = new LockIconViewController( mLockIconView, mStatusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt index d2c54b4..c372f45 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerWithCoroutinesTest.kt
@@ -17,9 +17,11 @@ package com.android.keyguard import android.testing.AndroidTestingRunner +import android.view.View import androidx.test.filters.SmallTest import com.android.keyguard.LockIconView.ICON_LOCK import com.android.systemui.doze.util.getBurnInOffset +import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED @@ -117,6 +119,33 @@ verify(mLockIconView).setTranslationX(0f) } + @Test + fun testHideLockIconView_onLockscreenHostedDreamStateChanged() = + runBlocking(IMMEDIATE) { + // GIVEN starting state for the lock icon (keyguard) and wallpaper dream enabled + mFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, true) + setupShowLockIcon() + init(/* useMigrationFlag= */ true) + reset(mLockIconView) + + // WHEN dream starts + mUnderTest.mIsActiveDreamLockscreenHostedCallback.accept( + true /* isActiveDreamLockscreenHosted */ + ) + + // THEN the lock icon is hidden + verify(mLockIconView).visibility = View.INVISIBLE + reset(mLockIconView) + + // WHEN the device is no longer dreaming + mUnderTest.mIsActiveDreamLockscreenHostedCallback.accept( + false /* isActiveDreamLockscreenHosted */ + ) + + // THEN lock icon is visible + verify(mLockIconView).visibility = View.VISIBLE + } + companion object { private val IMMEDIATE = Dispatchers.Main.immediate }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java new file mode 100644 index 0000000..d44846e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerBaseTest.java
@@ -0,0 +1,295 @@ +/* + * Copyright (C) 2023 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; + +import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; + +import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR; +import static com.android.systemui.flags.Flags.KEYGUARD_TALKBACK_FIX; +import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; +import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.AlarmManager; +import android.app.Instrumentation; +import android.app.admin.DevicePolicyManager; +import android.app.admin.DevicePolicyResourcesManager; +import android.app.trust.TrustManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.hardware.fingerprint.FingerprintManager; +import android.os.Looper; +import android.os.UserManager; +import android.provider.DeviceConfig; +import android.testing.TestableLooper; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; + +import androidx.test.InstrumentationRegistry; + +import com.android.internal.app.IBatteryStats; +import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.keyguard.logging.KeyguardLogger; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.biometrics.AuthController; +import com.android.systemui.biometrics.FaceHelpMessageDeferral; +import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; +import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor; +import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dock.DockManager; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.keyguard.KeyguardIndication; +import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController; +import com.android.systemui.keyguard.ScreenLifecycle; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory; +import com.android.systemui.keyguard.util.IndicationHelper; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.KeyguardIndicationTextView; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; +import com.android.systemui.util.wakelock.WakeLockFake; + +import org.junit.After; +import org.junit.Before; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class KeyguardIndicationControllerBaseTest extends SysuiTestCase { + + protected static final String ORGANIZATION_NAME = "organization"; + + protected static final ComponentName DEVICE_OWNER_COMPONENT = new ComponentName( + "com.android.foo", + "bar"); + + protected static final int TEST_STRING_RES = R.string.keyguard_indication_trust_unlocked; + + protected String mDisclosureWithOrganization; + protected String mDisclosureGeneric; + protected String mFinancedDisclosureWithOrganization; + + @Mock + protected DevicePolicyManager mDevicePolicyManager; + @Mock + protected DevicePolicyResourcesManager mDevicePolicyResourcesManager; + @Mock + protected ViewGroup mIndicationArea; + @Mock + protected KeyguardStateController mKeyguardStateController; + @Mock + protected KeyguardIndicationTextView mIndicationAreaBottom; + @Mock + protected BroadcastDispatcher mBroadcastDispatcher; + @Mock + protected StatusBarStateController mStatusBarStateController; + @Mock + protected KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock + protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + @Mock + protected UserManager mUserManager; + @Mock + protected IBatteryStats mIBatteryStats; + @Mock + protected DockManager mDockManager; + @Mock + protected KeyguardIndicationRotateTextViewController mRotateTextViewController; + @Mock + protected FalsingManager mFalsingManager; + @Mock + protected LockPatternUtils mLockPatternUtils; + @Mock + protected KeyguardBypassController mKeyguardBypassController; + @Mock + protected AccessibilityManager mAccessibilityManager; + @Mock + protected FaceHelpMessageDeferral mFaceHelpMessageDeferral; + @Mock + protected AlternateBouncerInteractor mAlternateBouncerInteractor; + @Mock + protected ScreenLifecycle mScreenLifecycle; + @Mock + protected AuthController mAuthController; + @Mock + protected AlarmManager mAlarmManager; + @Mock + protected UserTracker mUserTracker; + @Captor + protected ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener; + @Captor + protected ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; + @Captor + protected ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor; + @Captor + protected ArgumentCaptor<KeyguardIndication> mKeyguardIndicationCaptor; + @Captor + protected ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor; + @Captor + protected ArgumentCaptor<KeyguardStateController.Callback> + mKeyguardStateControllerCallbackCaptor; + @Captor + protected ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor; + protected KeyguardStateController.Callback mKeyguardStateControllerCallback; + protected KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback; + protected StatusBarStateController.StateListener mStatusBarStateListener; + protected ScreenLifecycle.Observer mScreenObserver; + protected BroadcastReceiver mBroadcastReceiver; + protected IndicationHelper mIndicationHelper; + protected FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); + protected TestableLooper mTestableLooper; + protected final int mCurrentUserId = 1; + + protected KeyguardIndicationTextView mTextView; // AOD text + + protected KeyguardIndicationController mController; + protected WakeLockFake.Builder mWakeLockBuilder; + protected WakeLockFake mWakeLock; + protected Instrumentation mInstrumentation; + protected FakeFeatureFlags mFlags; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mInstrumentation = InstrumentationRegistry.getInstrumentation(); + mTestableLooper = TestableLooper.get(this); + mTextView = new KeyguardIndicationTextView(mContext); + mTextView.setAnimationsEnabled(false); + + // TODO(b/259908270): remove + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER, + DevicePolicyManager.ADD_ISFINANCED_DEVICE_FLAG, "true", + /* makeDefault= */ false); + mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); + mContext.addMockSystemService(UserManager.class, mUserManager); + mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class)); + mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class)); + mDisclosureWithOrganization = mContext.getString(R.string.do_disclosure_with_name, + ORGANIZATION_NAME); + mDisclosureGeneric = mContext.getString(R.string.do_disclosure_generic); + mFinancedDisclosureWithOrganization = mContext.getString( + R.string.do_financed_disclosure_with_name, ORGANIZATION_NAME); + + when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); + when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_ON); + when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true); + + when(mIndicationArea.findViewById(R.id.keyguard_indication_text_bottom)) + .thenReturn(mIndicationAreaBottom); + when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView); + + when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager); + when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) + .thenReturn(DEVICE_OWNER_COMPONENT); + when(mDevicePolicyManager.isFinancedDevice()).thenReturn(false); + // TODO(b/259908270): remove + when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) + .thenReturn(DEVICE_OWNER_TYPE_DEFAULT); + + when(mDevicePolicyResourcesManager.getString(anyString(), any())) + .thenReturn(mDisclosureGeneric); + when(mDevicePolicyResourcesManager.getString(anyString(), any(), anyString())) + .thenReturn(mDisclosureWithOrganization); + when(mUserTracker.getUserId()).thenReturn(mCurrentUserId); + + mIndicationHelper = new IndicationHelper(mKeyguardUpdateMonitor); + + mWakeLock = new WakeLockFake(); + mWakeLockBuilder = new WakeLockFake.Builder(mContext); + mWakeLockBuilder.setWakeLock(mWakeLock); + } + + @After + public void tearDown() throws Exception { + mTextView.setAnimationsEnabled(true); + if (mController != null) { + mController.destroy(); + mController = null; + } + } + + protected void createController() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + mFlags = new FakeFeatureFlags(); + mFlags.set(KEYGUARD_TALKBACK_FIX, true); + mFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false); + mFlags.set(FACE_AUTH_REFACTOR, false); + mController = new KeyguardIndicationController( + mContext, + mTestableLooper.getLooper(), + mWakeLockBuilder, + mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor, + mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats, + mUserManager, mExecutor, mExecutor, mFalsingManager, + mAuthController, mLockPatternUtils, mScreenLifecycle, + mKeyguardBypassController, mAccessibilityManager, + mFaceHelpMessageDeferral, mock(KeyguardLogger.class), + mAlternateBouncerInteractor, + mAlarmManager, + mUserTracker, + mock(BouncerMessageInteractor.class), + mFlags, + mIndicationHelper, + KeyguardInteractorFactory.create(mFlags).getKeyguardInteractor() + ); + mController.init(); + mController.setIndicationArea(mIndicationArea); + verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); + mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue(); + verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiverCaptor.capture(), any()); + mBroadcastReceiver = mBroadcastReceiverCaptor.getValue(); + mController.mRotateTextViewController = mRotateTextViewController; + mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); + clearInvocations(mIBatteryStats); + + verify(mKeyguardStateController).addCallback( + mKeyguardStateControllerCallbackCaptor.capture()); + mKeyguardStateControllerCallback = mKeyguardStateControllerCallbackCaptor.getValue(); + + verify(mKeyguardUpdateMonitor).registerCallback( + mKeyguardUpdateMonitorCallbackCaptor.capture()); + mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue(); + + verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); + mScreenObserver = mScreenObserverCaptor.getValue(); + + mExecutor.runAllReady(); + reset(mRotateTextViewController); + } +}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index b1f5dde..8cf005dc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -11,12 +11,11 @@ * 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 + * limitations under the License. */ package com.android.systemui.statusbar; -import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK; @@ -26,7 +25,6 @@ import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; -import static com.android.systemui.flags.Flags.KEYGUARD_TALKBACK_FIX; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE; @@ -38,7 +36,6 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST; import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_OFF; -import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON; import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_TURNING_ON; import static com.google.common.truth.Truth.assertThat; @@ -60,73 +57,28 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import android.app.AlarmManager; -import android.app.Instrumentation; -import android.app.admin.DevicePolicyManager; -import android.app.admin.DevicePolicyResourcesManager; -import android.app.trust.TrustManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.graphics.Color; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricSourceType; -import android.hardware.fingerprint.FingerprintManager; import android.os.BatteryManager; -import android.os.Looper; import android.os.RemoteException; -import android.os.UserManager; -import android.provider.DeviceConfig; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityManager; -import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; -import com.android.internal.app.IBatteryStats; -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.TrustGrantFlags; -import com.android.keyguard.logging.KeyguardLogger; import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.R; -import com.android.systemui.SysuiTestCase; -import com.android.systemui.biometrics.AuthController; -import com.android.systemui.biometrics.FaceHelpMessageDeferral; -import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; -import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor; -import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dock.DockManager; -import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.keyguard.KeyguardIndication; import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController; -import com.android.systemui.keyguard.ScreenLifecycle; -import com.android.systemui.keyguard.util.IndicationHelper; -import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.KeyguardIndicationTextView; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.time.FakeSystemClock; -import com.android.systemui.util.wakelock.WakeLockFake; -import org.junit.After; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import java.text.NumberFormat; import java.util.Collections; @@ -137,205 +89,7 @@ @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class KeyguardIndicationControllerTest extends SysuiTestCase { - - private static final String ORGANIZATION_NAME = "organization"; - - private static final ComponentName DEVICE_OWNER_COMPONENT = new ComponentName("com.android.foo", - "bar"); - - private static final int TEST_STRING_RES = R.string.keyguard_indication_trust_unlocked; - - private String mDisclosureWithOrganization; - private String mDisclosureGeneric; - private String mFinancedDisclosureWithOrganization; - - @Mock - private DevicePolicyManager mDevicePolicyManager; - @Mock - private DevicePolicyResourcesManager mDevicePolicyResourcesManager; - @Mock - private ViewGroup mIndicationArea; - @Mock - private KeyguardStateController mKeyguardStateController; - @Mock - private KeyguardIndicationTextView mIndicationAreaBottom; - @Mock - private BroadcastDispatcher mBroadcastDispatcher; - @Mock - private StatusBarStateController mStatusBarStateController; - @Mock - private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - @Mock - private UserManager mUserManager; - @Mock - private IBatteryStats mIBatteryStats; - @Mock - private DockManager mDockManager; - @Mock - private KeyguardIndicationRotateTextViewController mRotateTextViewController; - @Mock - private FalsingManager mFalsingManager; - @Mock - private LockPatternUtils mLockPatternUtils; - @Mock - private KeyguardBypassController mKeyguardBypassController; - @Mock - private AccessibilityManager mAccessibilityManager; - @Mock - private FaceHelpMessageDeferral mFaceHelpMessageDeferral; - @Mock - private AlternateBouncerInteractor mAlternateBouncerInteractor; - @Mock - private ScreenLifecycle mScreenLifecycle; - @Mock - private AuthController mAuthController; - @Mock - private AlarmManager mAlarmManager; - @Mock - private UserTracker mUserTracker; - @Captor - private ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener; - @Captor - private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; - @Captor - private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor; - @Captor - private ArgumentCaptor<KeyguardIndication> mKeyguardIndicationCaptor; - @Captor - private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor; - @Captor - private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallbackCaptor; - @Captor - private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor; - private KeyguardStateController.Callback mKeyguardStateControllerCallback; - private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback; - private StatusBarStateController.StateListener mStatusBarStateListener; - private ScreenLifecycle.Observer mScreenObserver; - private BroadcastReceiver mBroadcastReceiver; - private IndicationHelper mIndicationHelper; - private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); - private TestableLooper mTestableLooper; - private final int mCurrentUserId = 1; - - private KeyguardIndicationTextView mTextView; // AOD text - - private KeyguardIndicationController mController; - private WakeLockFake.Builder mWakeLockBuilder; - private WakeLockFake mWakeLock; - private Instrumentation mInstrumentation; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mInstrumentation = InstrumentationRegistry.getInstrumentation(); - mTestableLooper = TestableLooper.get(this); - mTextView = new KeyguardIndicationTextView(mContext); - mTextView.setAnimationsEnabled(false); - - // TODO(b/259908270): remove - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER, - DevicePolicyManager.ADD_ISFINANCED_DEVICE_FLAG, "true", - /* makeDefault= */ false); - mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); - mContext.addMockSystemService(UserManager.class, mUserManager); - mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class)); - mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class)); - mDisclosureWithOrganization = mContext.getString(R.string.do_disclosure_with_name, - ORGANIZATION_NAME); - mDisclosureGeneric = mContext.getString(R.string.do_disclosure_generic); - mFinancedDisclosureWithOrganization = mContext.getString( - R.string.do_financed_disclosure_with_name, ORGANIZATION_NAME); - - when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); - when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_ON); - when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true); - - when(mIndicationArea.findViewById(R.id.keyguard_indication_text_bottom)) - .thenReturn(mIndicationAreaBottom); - when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView); - - when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager); - when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) - .thenReturn(DEVICE_OWNER_COMPONENT); - when(mDevicePolicyManager.isFinancedDevice()).thenReturn(false); - // TODO(b/259908270): remove - when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) - .thenReturn(DEVICE_OWNER_TYPE_DEFAULT); - - when(mDevicePolicyResourcesManager.getString(anyString(), any())) - .thenReturn(mDisclosureGeneric); - when(mDevicePolicyResourcesManager.getString(anyString(), any(), anyString())) - .thenReturn(mDisclosureWithOrganization); - when(mUserTracker.getUserId()).thenReturn(mCurrentUserId); - - mIndicationHelper = new IndicationHelper(mKeyguardUpdateMonitor); - - mWakeLock = new WakeLockFake(); - mWakeLockBuilder = new WakeLockFake.Builder(mContext); - mWakeLockBuilder.setWakeLock(mWakeLock); - } - - @After - public void tearDown() throws Exception { - mTextView.setAnimationsEnabled(true); - if (mController != null) { - mController.destroy(); - mController = null; - } - } - - private void createController() { - if (Looper.myLooper() == null) { - Looper.prepare(); - } - - FakeFeatureFlags flags = new FakeFeatureFlags(); - flags.set(KEYGUARD_TALKBACK_FIX, true); - mController = new KeyguardIndicationController( - mContext, - mTestableLooper.getLooper(), - mWakeLockBuilder, - mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor, - mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats, - mUserManager, mExecutor, mExecutor, mFalsingManager, - mAuthController, mLockPatternUtils, mScreenLifecycle, - mKeyguardBypassController, mAccessibilityManager, - mFaceHelpMessageDeferral, mock(KeyguardLogger.class), - mAlternateBouncerInteractor, - mAlarmManager, - mUserTracker, - mock(BouncerMessageInteractor.class), - flags, - mIndicationHelper - ); - mController.init(); - mController.setIndicationArea(mIndicationArea); - verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); - mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue(); - verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiverCaptor.capture(), any()); - mBroadcastReceiver = mBroadcastReceiverCaptor.getValue(); - mController.mRotateTextViewController = mRotateTextViewController; - mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); - clearInvocations(mIBatteryStats); - - verify(mKeyguardStateController).addCallback( - mKeyguardStateControllerCallbackCaptor.capture()); - mKeyguardStateControllerCallback = mKeyguardStateControllerCallbackCaptor.getValue(); - - verify(mKeyguardUpdateMonitor).registerCallback( - mKeyguardUpdateMonitorCallbackCaptor.capture()); - mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue(); - - verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); - mScreenObserver = mScreenObserverCaptor.getValue(); - - mExecutor.runAllReady(); - reset(mRotateTextViewController); - } - +public class KeyguardIndicationControllerTest extends KeyguardIndicationControllerBaseTest { @Test public void createController_setIndicationAreaAgain_destroysPreviousRotateTextViewController() { // GIVEN a controller with a mocked rotate text view controlller
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerWithCoroutinesTest.kt new file mode 100644 index 0000000..cdc7520 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerWithCoroutinesTest.kt
@@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 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 + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +@RunWith(AndroidTestingRunner::class) +@SmallTest +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class KeyguardIndicationControllerWithCoroutinesTest : KeyguardIndicationControllerBaseTest() { + @Test + fun testIndicationAreaVisibility_onLockscreenHostedDreamStateChanged() = + runBlocking(IMMEDIATE) { + // GIVEN starting state for keyguard indication and wallpaper dream enabled + createController() + mFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, true) + mController.setVisible(true) + + // THEN indication area is visible + verify(mIndicationArea, times(2)).visibility = View.VISIBLE + + // WHEN the device is dreaming with lockscreen hosted dream + mController.mIsActiveDreamLockscreenHostedCallback.accept( + true /* isActiveDreamLockscreenHosted */ + ) + mExecutor.runAllReady() + + // THEN the indication area is hidden + verify(mIndicationArea).visibility = View.GONE + + // WHEN the device stops dreaming with lockscreen hosted dream + mController.mIsActiveDreamLockscreenHostedCallback.accept( + false /* isActiveDreamLockscreenHosted */ + ) + mExecutor.runAllReady() + + // THEN indication area is set visible + verify(mIndicationArea, times(3)).visibility = View.VISIBLE + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +}