Merge "Split shade expansion: adjust alpha interpolation to match motion specs" into tm-qpr-dev am: 186e7cbd8f am: 83c4acd066
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21463824 Change-Id: I6200772f0bdfe9dba55982277af2c4d53c7551a2 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -70,6 +70,8 @@ import com.android.systemui.screenshot.dagger.ScreenshotModule;
|
||||
import com.android.systemui.security.data.repository.SecurityRepositoryModule;
|
||||
import com.android.systemui.settings.DisplayTracker;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
|
||||
import com.android.systemui.smartspace.dagger.SmartspaceModule;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
@@ -309,4 +311,8 @@ public abstract class SystemUIModule {
|
||||
|
||||
@Binds
|
||||
abstract FgsManagerController bindFgsManagerController(FgsManagerControllerImpl impl);
|
||||
|
||||
@Binds
|
||||
abstract LargeScreenShadeInterpolator largeScreensShadeInterpolator(
|
||||
LargeScreenShadeInterpolatorImpl impl);
|
||||
}
|
||||
|
||||
@@ -656,4 +656,9 @@ object Flags {
|
||||
// TODO(b/259428678): Tracking Bug
|
||||
@JvmField
|
||||
val KEYBOARD_BACKLIGHT_INDICATOR = unreleasedFlag(2601, "keyboard_backlight_indicator")
|
||||
|
||||
// TODO(b/272036292): Tracking Bug
|
||||
@JvmField
|
||||
val LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION =
|
||||
unreleasedFlag(2602, "large_shade_granular_alpha_interpolation")
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.animation.ShadeInterpolation;
|
||||
import com.android.systemui.compose.ComposeFacade;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.media.controls.ui.MediaHost;
|
||||
import com.android.systemui.plugins.qs.QS;
|
||||
import com.android.systemui.plugins.qs.QSContainerController;
|
||||
@@ -59,6 +61,7 @@ import com.android.systemui.qs.dagger.QSFragmentComponent;
|
||||
import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
|
||||
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
@@ -111,6 +114,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
private final MediaHost mQqsMediaHost;
|
||||
private final QSFragmentComponent.Factory mQsComponentFactory;
|
||||
private final QSFragmentDisableFlagsLogger mQsFragmentDisableFlagsLogger;
|
||||
private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final QSLogger mLogger;
|
||||
private final FooterActionsController mFooterActionsController;
|
||||
private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
|
||||
@@ -158,12 +163,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
// visible;
|
||||
private boolean mQsVisible;
|
||||
|
||||
/**
|
||||
* Whether the notification panel uses the full width of the screen.
|
||||
*
|
||||
* Usually {@code true} on small screens, and {@code false} on large screens.
|
||||
*/
|
||||
private boolean mIsNotificationPanelFullWidth;
|
||||
private boolean mIsSmallScreen;
|
||||
|
||||
@Inject
|
||||
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
|
||||
@@ -175,13 +175,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
|
||||
DumpManager dumpManager, QSLogger qsLogger,
|
||||
FooterActionsController footerActionsController,
|
||||
FooterActionsViewModel.Factory footerActionsViewModelFactory) {
|
||||
FooterActionsViewModel.Factory footerActionsViewModelFactory,
|
||||
LargeScreenShadeInterpolator largeScreenShadeInterpolator,
|
||||
FeatureFlags featureFlags) {
|
||||
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
|
||||
mQsMediaHost = qsMediaHost;
|
||||
mQqsMediaHost = qqsMediaHost;
|
||||
mQsComponentFactory = qsComponentFactory;
|
||||
mQsFragmentDisableFlagsLogger = qsFragmentDisableFlagsLogger;
|
||||
mLogger = qsLogger;
|
||||
mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
|
||||
mFeatureFlags = featureFlags;
|
||||
commandQueue.observe(getLifecycle(), this);
|
||||
mBypassController = keyguardBypassController;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
@@ -606,7 +610,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
|
||||
@Override
|
||||
public void setIsNotificationPanelFullWidth(boolean isFullWidth) {
|
||||
mIsNotificationPanelFullWidth = isFullWidth;
|
||||
mIsSmallScreen = isFullWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -709,7 +713,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
}
|
||||
|
||||
private float calculateAlphaProgress(float panelExpansionFraction) {
|
||||
if (mIsNotificationPanelFullWidth) {
|
||||
if (mIsSmallScreen) {
|
||||
// Small screens. QS alpha is not animated.
|
||||
return 1;
|
||||
}
|
||||
@@ -744,7 +748,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
// Alpha progress should be linear on lockscreen shade expansion.
|
||||
return progress;
|
||||
}
|
||||
return ShadeInterpolation.getContentAlpha(progress);
|
||||
if (mIsSmallScreen || !mFeatureFlags.isEnabled(
|
||||
Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
|
||||
return ShadeInterpolation.getContentAlpha(progress);
|
||||
} else {
|
||||
return mLargeScreenShadeInterpolator.getQsAlpha(progress);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -2956,7 +2956,10 @@ public final class NotificationPanelViewController implements Dumpable {
|
||||
mHeadsUpStartHeight = startHeight;
|
||||
float scrimMinFraction;
|
||||
if (mSplitShadeEnabled) {
|
||||
boolean highHun = mHeadsUpStartHeight * 2.5 > mSplitShadeScrimTransitionDistance;
|
||||
boolean highHun = mHeadsUpStartHeight * 2.5
|
||||
>
|
||||
(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
|
||||
? mSplitShadeFullTransitionDistance : mSplitShadeScrimTransitionDistance);
|
||||
// if HUN height is higher than 40% of predefined transition distance, it means HUN
|
||||
// is too high for regular transition. In that case we need to calculate transition
|
||||
// distance - here we take scrim transition distance as equal to shade transition
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.shade.transition
|
||||
|
||||
import android.util.MathUtils
|
||||
import com.android.systemui.animation.ShadeInterpolation
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Interpolator responsible for the shade when in portrait on a large screen. */
|
||||
internal class LargeScreenPortraitShadeInterpolator @Inject internal constructor() :
|
||||
LargeScreenShadeInterpolator {
|
||||
|
||||
override fun getBehindScrimAlpha(fraction: Float): Float {
|
||||
return MathUtils.constrainedMap(0f, 1f, 0f, 0.3f, fraction)
|
||||
}
|
||||
|
||||
override fun getNotificationScrimAlpha(fraction: Float): Float {
|
||||
return MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f, fraction)
|
||||
}
|
||||
|
||||
override fun getNotificationContentAlpha(fraction: Float): Float {
|
||||
return ShadeInterpolation.getContentAlpha(fraction)
|
||||
}
|
||||
|
||||
override fun getNotificationFooterAlpha(fraction: Float): Float {
|
||||
return ShadeInterpolation.getContentAlpha(fraction)
|
||||
}
|
||||
|
||||
override fun getQsAlpha(fraction: Float): Float {
|
||||
return ShadeInterpolation.getContentAlpha(fraction)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.shade.transition
|
||||
|
||||
/** An interpolator interface for the shade expansion. */
|
||||
interface LargeScreenShadeInterpolator {
|
||||
|
||||
/** Returns the alpha for the behind/back scrim. */
|
||||
fun getBehindScrimAlpha(fraction: Float): Float
|
||||
|
||||
/** Returns the alpha for the notification scrim. */
|
||||
fun getNotificationScrimAlpha(fraction: Float): Float
|
||||
|
||||
/** Returns the alpha for the notifications. */
|
||||
fun getNotificationContentAlpha(fraction: Float): Float
|
||||
|
||||
/** Returns the alpha for the notifications footer (Manager, Clear All). */
|
||||
fun getNotificationFooterAlpha(fraction: Float): Float
|
||||
|
||||
/** Returns the alpha for the QS panel. */
|
||||
fun getQsAlpha(fraction: Float): Float
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.shade.transition
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.util.LargeScreenUtils
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Interpolator responsible for the shade when on large screens. */
|
||||
@SysUISingleton
|
||||
internal class LargeScreenShadeInterpolatorImpl
|
||||
@Inject
|
||||
internal constructor(
|
||||
configurationController: ConfigurationController,
|
||||
private val context: Context,
|
||||
private val splitShadeInterpolator: SplitShadeInterpolator,
|
||||
private val portraitShadeInterpolator: LargeScreenPortraitShadeInterpolator,
|
||||
) : LargeScreenShadeInterpolator {
|
||||
|
||||
private var inSplitShade = false
|
||||
|
||||
init {
|
||||
configurationController.addCallback(
|
||||
object : ConfigurationController.ConfigurationListener {
|
||||
override fun onConfigChanged(newConfig: Configuration?) {
|
||||
updateResources()
|
||||
}
|
||||
}
|
||||
)
|
||||
updateResources()
|
||||
}
|
||||
|
||||
private fun updateResources() {
|
||||
inSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(context.resources)
|
||||
}
|
||||
|
||||
private val impl: LargeScreenShadeInterpolator
|
||||
get() =
|
||||
if (inSplitShade) {
|
||||
splitShadeInterpolator
|
||||
} else {
|
||||
portraitShadeInterpolator
|
||||
}
|
||||
|
||||
override fun getBehindScrimAlpha(fraction: Float) = impl.getBehindScrimAlpha(fraction)
|
||||
|
||||
override fun getNotificationScrimAlpha(fraction: Float) =
|
||||
impl.getNotificationScrimAlpha(fraction)
|
||||
|
||||
override fun getNotificationContentAlpha(fraction: Float) =
|
||||
impl.getNotificationContentAlpha(fraction)
|
||||
|
||||
override fun getNotificationFooterAlpha(fraction: Float) =
|
||||
impl.getNotificationFooterAlpha(fraction)
|
||||
|
||||
override fun getQsAlpha(fraction: Float) = impl.getQsAlpha(fraction)
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import com.android.systemui.R
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.shade.PanelState
|
||||
import com.android.systemui.shade.STATE_OPENING
|
||||
import com.android.systemui.shade.ShadeExpansionChangeEvent
|
||||
@@ -45,7 +47,8 @@ constructor(
|
||||
private val scrimController: ScrimController,
|
||||
@Main private val resources: Resources,
|
||||
private val statusBarStateController: SysuiStatusBarStateController,
|
||||
private val headsUpManager: HeadsUpManager
|
||||
private val headsUpManager: HeadsUpManager,
|
||||
private val featureFlags: FeatureFlags,
|
||||
) {
|
||||
|
||||
private var inSplitShade = false
|
||||
@@ -106,7 +109,8 @@ constructor(
|
||||
// in case of HUN we can't always use predefined distances to manage scrim
|
||||
// transition because dragDownPxAmount can start from value bigger than
|
||||
// splitShadeScrimTransitionDistance
|
||||
!headsUpManager.isTrackingHeadsUp
|
||||
!headsUpManager.isTrackingHeadsUp &&
|
||||
!featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
|
||||
|
||||
private fun isScreenUnlocked() =
|
||||
statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.shade.transition
|
||||
|
||||
import android.util.MathUtils
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Interpolator responsible for the split shade. */
|
||||
internal class SplitShadeInterpolator @Inject internal constructor() :
|
||||
LargeScreenShadeInterpolator {
|
||||
|
||||
override fun getBehindScrimAlpha(fraction: Float): Float {
|
||||
// Start delay: 0%
|
||||
// Duration: 40%
|
||||
// End: 40%
|
||||
return mapFraction(start = 0f, end = 0.4f, fraction)
|
||||
}
|
||||
|
||||
override fun getNotificationScrimAlpha(fraction: Float): Float {
|
||||
// Start delay: 39%
|
||||
// Duration: 27%
|
||||
// End: 66%
|
||||
return mapFraction(start = 0.39f, end = 0.66f, fraction)
|
||||
}
|
||||
|
||||
override fun getNotificationContentAlpha(fraction: Float): Float {
|
||||
return getNotificationScrimAlpha(fraction)
|
||||
}
|
||||
|
||||
override fun getNotificationFooterAlpha(fraction: Float): Float {
|
||||
// Start delay: 57.6%
|
||||
// Duration: 32.1%
|
||||
// End: 89.7%
|
||||
return mapFraction(start = 0.576f, end = 0.897f, fraction)
|
||||
}
|
||||
|
||||
override fun getQsAlpha(fraction: Float): Float {
|
||||
return getNotificationScrimAlpha(fraction)
|
||||
}
|
||||
|
||||
private fun mapFraction(start: Float, end: Float, fraction: Float) =
|
||||
MathUtils.constrainedMap(
|
||||
/* rangeMin= */ 0f,
|
||||
/* rangeMax= */ 1f,
|
||||
/* valueMin= */ start,
|
||||
/* valueMax= */ end,
|
||||
/* value= */ fraction
|
||||
)
|
||||
}
|
||||
@@ -39,7 +39,10 @@ import com.android.internal.policy.SystemBarUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.animation.ShadeInterpolation;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.notification.LegacySourceType;
|
||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||
import com.android.systemui.statusbar.notification.SourceType;
|
||||
@@ -216,7 +219,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
||||
if (ambientState.isBouncerInTransit()) {
|
||||
viewState.setAlpha(aboutToShowBouncerProgress(expansion));
|
||||
} else {
|
||||
viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
|
||||
FeatureFlags flags = ambientState.getFeatureFlags();
|
||||
if (ambientState.isSmallScreen() || !flags.isEnabled(
|
||||
Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
|
||||
viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
|
||||
} else {
|
||||
LargeScreenShadeInterpolator interpolator =
|
||||
ambientState.getLargeScreenShadeInterpolator();
|
||||
viewState.setAlpha(interpolator.getNotificationContentAlpha(expansion));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
viewState.setAlpha(1f - ambientState.getHideAmount());
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.NotificationShelf;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
@@ -55,6 +57,8 @@ public class AmbientState implements Dumpable {
|
||||
|
||||
private final SectionProvider mSectionProvider;
|
||||
private final BypassController mBypassController;
|
||||
private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
/**
|
||||
* Used to read bouncer states.
|
||||
*/
|
||||
@@ -84,7 +88,7 @@ public class AmbientState implements Dumpable {
|
||||
private float mExpandingVelocity;
|
||||
private boolean mPanelTracking;
|
||||
private boolean mExpansionChanging;
|
||||
private boolean mPanelFullWidth;
|
||||
private boolean mIsSmallScreen;
|
||||
private boolean mPulsing;
|
||||
private boolean mUnlockHintRunning;
|
||||
private float mHideAmount;
|
||||
@@ -252,10 +256,14 @@ public class AmbientState implements Dumpable {
|
||||
@NonNull DumpManager dumpManager,
|
||||
@NonNull SectionProvider sectionProvider,
|
||||
@NonNull BypassController bypassController,
|
||||
@Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
|
||||
@Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||
@NonNull LargeScreenShadeInterpolator largeScreenShadeInterpolator,
|
||||
@NonNull FeatureFlags featureFlags) {
|
||||
mSectionProvider = sectionProvider;
|
||||
mBypassController = bypassController;
|
||||
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
|
||||
mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
|
||||
mFeatureFlags = featureFlags;
|
||||
reload(context);
|
||||
dumpManager.registerDumpable(this);
|
||||
}
|
||||
@@ -574,12 +582,12 @@ public class AmbientState implements Dumpable {
|
||||
return mPanelTracking;
|
||||
}
|
||||
|
||||
public boolean isPanelFullWidth() {
|
||||
return mPanelFullWidth;
|
||||
public boolean isSmallScreen() {
|
||||
return mIsSmallScreen;
|
||||
}
|
||||
|
||||
public void setPanelFullWidth(boolean panelFullWidth) {
|
||||
mPanelFullWidth = panelFullWidth;
|
||||
public void setSmallScreen(boolean smallScreen) {
|
||||
mIsSmallScreen = smallScreen;
|
||||
}
|
||||
|
||||
public void setUnlockHintRunning(boolean unlockHintRunning) {
|
||||
@@ -736,6 +744,14 @@ public class AmbientState implements Dumpable {
|
||||
return mIsClosing;
|
||||
}
|
||||
|
||||
public LargeScreenShadeInterpolator getLargeScreenShadeInterpolator() {
|
||||
return mLargeScreenShadeInterpolator;
|
||||
}
|
||||
|
||||
public FeatureFlags getFeatureFlags() {
|
||||
return mFeatureFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter pw, String[] args) {
|
||||
pw.println("mTopPadding=" + mTopPadding);
|
||||
@@ -751,7 +767,7 @@ public class AmbientState implements Dumpable {
|
||||
pw.println("mDimmed=" + mDimmed);
|
||||
pw.println("mStatusBarState=" + mStatusBarState);
|
||||
pw.println("mExpansionChanging=" + mExpansionChanging);
|
||||
pw.println("mPanelFullWidth=" + mPanelFullWidth);
|
||||
pw.println("mPanelFullWidth=" + mIsSmallScreen);
|
||||
pw.println("mPulsing=" + mPulsing);
|
||||
pw.println("mPulseHeight=" + mPulseHeight);
|
||||
pw.println("mTrackedHeadsUpRow.key=" + logKey(mTrackedHeadsUpRow));
|
||||
|
||||
@@ -5223,7 +5223,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
public void setIsFullWidth(boolean isFullWidth) {
|
||||
mAmbientState.setPanelFullWidth(isFullWidth);
|
||||
mAmbientState.setSmallScreen(isFullWidth);
|
||||
}
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
|
||||
@@ -70,7 +70,6 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEv
|
||||
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.shade.transition.ShadeTransitionController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
||||
@@ -172,7 +171,6 @@ public class NotificationStackScrollLayoutController {
|
||||
private final CentralSurfaces mCentralSurfaces;
|
||||
private final SectionHeaderController mSilentHeaderController;
|
||||
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
private final ShadeTransitionController mShadeTransitionController;
|
||||
private final InteractionJankMonitor mJankMonitor;
|
||||
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||
private final StackStateLogger mStackStateLogger;
|
||||
@@ -664,7 +662,6 @@ public class NotificationStackScrollLayoutController {
|
||||
NotifPipelineFlags notifPipelineFlags,
|
||||
NotifCollection notifCollection,
|
||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||
ShadeTransitionController shadeTransitionController,
|
||||
UiEventLogger uiEventLogger,
|
||||
NotificationRemoteInputManager remoteInputManager,
|
||||
VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
|
||||
@@ -697,7 +694,6 @@ public class NotificationStackScrollLayoutController {
|
||||
mMetricsLogger = metricsLogger;
|
||||
mDumpManager = dumpManager;
|
||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||
mShadeTransitionController = shadeTransitionController;
|
||||
mFalsingCollector = falsingCollector;
|
||||
mFalsingManager = falsingManager;
|
||||
mResources = resources;
|
||||
@@ -781,7 +777,6 @@ public class NotificationStackScrollLayoutController {
|
||||
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
|
||||
|
||||
mLockscreenShadeTransitionController.setStackScroller(this);
|
||||
mShadeTransitionController.setNotificationStackScrollLayoutController(this);
|
||||
|
||||
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ import com.android.internal.policy.SystemBarUtils;
|
||||
import com.android.keyguard.BouncerPanelExpansionCalculator;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.ShadeInterpolation;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.EmptyShadeView;
|
||||
import com.android.systemui.statusbar.NotificationShelf;
|
||||
import com.android.systemui.statusbar.notification.LegacySourceType;
|
||||
@@ -135,7 +138,6 @@ public class StackScrollAlgorithm {
|
||||
AmbientState ambientState) {
|
||||
for (ExpandableView view : algorithmState.visibleChildren) {
|
||||
final ViewState viewState = view.getViewState();
|
||||
|
||||
final boolean isHunGoingToShade = ambientState.isShadeExpanded()
|
||||
&& view == ambientState.getTrackedHeadsUpRow();
|
||||
|
||||
@@ -148,9 +150,14 @@ public class StackScrollAlgorithm {
|
||||
} else if (ambientState.isExpansionChanging()) {
|
||||
// Adjust alpha for shade open & close.
|
||||
float expansion = ambientState.getExpansionFraction();
|
||||
viewState.setAlpha(ambientState.isBouncerInTransit()
|
||||
? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
|
||||
: ShadeInterpolation.getContentAlpha(expansion));
|
||||
if (ambientState.isBouncerInTransit()) {
|
||||
viewState.setAlpha(
|
||||
BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion));
|
||||
} else if (view instanceof FooterView) {
|
||||
viewState.setAlpha(interpolateFooterAlpha(ambientState));
|
||||
} else {
|
||||
viewState.setAlpha(interpolateNotificationContentAlpha(ambientState));
|
||||
}
|
||||
}
|
||||
|
||||
// For EmptyShadeView if on keyguard, we need to control the alpha to create
|
||||
@@ -182,6 +189,28 @@ public class StackScrollAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
private float interpolateFooterAlpha(AmbientState ambientState) {
|
||||
float expansion = ambientState.getExpansionFraction();
|
||||
FeatureFlags flags = ambientState.getFeatureFlags();
|
||||
if (ambientState.isSmallScreen()
|
||||
|| !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
|
||||
return ShadeInterpolation.getContentAlpha(expansion);
|
||||
}
|
||||
LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
|
||||
return interpolator.getNotificationFooterAlpha(expansion);
|
||||
}
|
||||
|
||||
private float interpolateNotificationContentAlpha(AmbientState ambientState) {
|
||||
float expansion = ambientState.getExpansionFraction();
|
||||
FeatureFlags flags = ambientState.getFeatureFlags();
|
||||
if (ambientState.isSmallScreen()
|
||||
|| !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
|
||||
return ShadeInterpolation.getContentAlpha(expansion);
|
||||
}
|
||||
LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
|
||||
return interpolator.getNotificationContentAlpha(expansion);
|
||||
}
|
||||
|
||||
/**
|
||||
* How expanded or collapsed notifications are when pulling down the shade.
|
||||
*
|
||||
|
||||
@@ -54,6 +54,8 @@ import com.android.systemui.animation.ShadeInterpolation;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
|
||||
@@ -62,6 +64,7 @@ import com.android.systemui.keyguard.shared.model.TransitionStep;
|
||||
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
import com.android.systemui.shade.NotificationPanelViewController;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.stack.ViewState;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
@@ -245,6 +248,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
private boolean mWallpaperVisibilityTimedOut;
|
||||
private int mScrimsVisibility;
|
||||
private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
|
||||
private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private Consumer<Integer> mScrimVisibleListener;
|
||||
private boolean mBlankScreen;
|
||||
private boolean mScreenBlankingCallbackCalled;
|
||||
@@ -293,8 +298,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
|
||||
KeyguardTransitionInteractor keyguardTransitionInteractor,
|
||||
SysuiStatusBarStateController sysuiStatusBarStateController,
|
||||
@Main CoroutineDispatcher mainDispatcher) {
|
||||
@Main CoroutineDispatcher mainDispatcher,
|
||||
LargeScreenShadeInterpolator largeScreenShadeInterpolator,
|
||||
FeatureFlags featureFlags) {
|
||||
mScrimStateListener = lightBarController::setScrimState;
|
||||
mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
|
||||
mFeatureFlags = featureFlags;
|
||||
mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
|
||||
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
@@ -850,16 +859,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
if (!mScreenOffAnimationController.shouldExpandNotifications()
|
||||
&& !mAnimatingPanelExpansionOnUnlock
|
||||
&& !occluding) {
|
||||
if (mClipsQsScrim) {
|
||||
if (mTransparentScrimBackground) {
|
||||
mBehindAlpha = 0;
|
||||
mNotificationsAlpha = 0;
|
||||
} else if (mClipsQsScrim) {
|
||||
float behindFraction = getInterpolatedFraction();
|
||||
behindFraction = (float) Math.pow(behindFraction, 0.8f);
|
||||
mBehindAlpha = mTransparentScrimBackground ? 0 : 1;
|
||||
mNotificationsAlpha =
|
||||
mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
|
||||
mBehindAlpha = 1;
|
||||
mNotificationsAlpha = behindFraction * mDefaultScrimAlpha;
|
||||
} else {
|
||||
if (mTransparentScrimBackground) {
|
||||
mBehindAlpha = 0;
|
||||
mNotificationsAlpha = 0;
|
||||
if (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
|
||||
mBehindAlpha = mLargeScreenShadeInterpolator.getBehindScrimAlpha(
|
||||
mPanelExpansionFraction * mDefaultScrimAlpha);
|
||||
mNotificationsAlpha =
|
||||
mLargeScreenShadeInterpolator.getNotificationScrimAlpha(
|
||||
mPanelExpansionFraction);
|
||||
} else {
|
||||
// Behind scrim will finish fading in at 30% expansion.
|
||||
float behindFraction = MathUtils
|
||||
|
||||
@@ -52,6 +52,8 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiBaseFragmentTest;
|
||||
import com.android.systemui.animation.ShadeInterpolation;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.media.controls.ui.MediaHost;
|
||||
import com.android.systemui.qs.customize.QSCustomizerController;
|
||||
import com.android.systemui.qs.dagger.QSFragmentComponent;
|
||||
@@ -60,6 +62,7 @@ import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
|
||||
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
import com.android.systemui.settings.FakeDisplayTracker;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
@@ -103,6 +106,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
|
||||
@Mock private QSSquishinessController mSquishinessController;
|
||||
@Mock private FooterActionsViewModel mFooterActionsViewModel;
|
||||
@Mock private FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
|
||||
@Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
private View mQsFragmentView;
|
||||
|
||||
public QSFragmentTest() {
|
||||
@@ -148,13 +153,51 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToFullShade_setsAlphaUsingShadeInterpolator() {
|
||||
public void transitionToFullShade_smallScreen_alphaAlways1() {
|
||||
QSFragment fragment = resumeAndGetFragment();
|
||||
setIsSmallScreen();
|
||||
setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
|
||||
boolean isTransitioningToFullShade = true;
|
||||
float transitionProgress = 0.5f;
|
||||
float squishinessFraction = 0.5f;
|
||||
|
||||
fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
|
||||
squishinessFraction);
|
||||
|
||||
assertThat(mQsFragmentView.getAlpha()).isEqualTo(1f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToFullShade_largeScreen_flagEnabled_alphaLargeScreenShadeInterpolator() {
|
||||
when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(true);
|
||||
QSFragment fragment = resumeAndGetFragment();
|
||||
setIsLargeScreen();
|
||||
setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
|
||||
boolean isTransitioningToFullShade = true;
|
||||
float transitionProgress = 0.5f;
|
||||
float squishinessFraction = 0.5f;
|
||||
when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
|
||||
|
||||
fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
|
||||
squishinessFraction);
|
||||
|
||||
assertThat(mQsFragmentView.getAlpha())
|
||||
.isEqualTo(123f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToFullShade_largeScreen_flagDisabled_alphaStandardInterpolator() {
|
||||
when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(false);
|
||||
QSFragment fragment = resumeAndGetFragment();
|
||||
setIsLargeScreen();
|
||||
setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
|
||||
boolean isTransitioningToFullShade = true;
|
||||
float transitionProgress = 0.5f;
|
||||
float squishinessFraction = 0.5f;
|
||||
when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
|
||||
|
||||
fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
|
||||
squishinessFraction);
|
||||
|
||||
@@ -514,7 +557,9 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
|
||||
mock(DumpManager.class),
|
||||
mock(QSLogger.class),
|
||||
mock(FooterActionsController.class),
|
||||
mFooterActionsViewModelFactory);
|
||||
mFooterActionsViewModelFactory,
|
||||
mLargeScreenShadeInterpolator,
|
||||
mFeatureFlags);
|
||||
}
|
||||
|
||||
private void setUpOther() {
|
||||
@@ -622,4 +667,12 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
|
||||
return null;
|
||||
}).when(view).getLocationOnScreen(any(int[].class));
|
||||
}
|
||||
|
||||
private void setIsLargeScreen() {
|
||||
getFragment().setIsNotificationPanelFullWidth(false);
|
||||
}
|
||||
|
||||
private void setIsSmallScreen() {
|
||||
getFragment().setIsNotificationPanelFullWidth(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import static com.android.keyguard.KeyguardClockSwitch.LARGE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -35,6 +33,8 @@ import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
|
||||
|
||||
import android.annotation.IdRes;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.res.Configuration;
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.android.systemui.shade.transition
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.policy.FakeConfigurationController
|
||||
import com.google.common.truth.Expect
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class LargeScreenShadeInterpolatorImplTest : SysuiTestCase() {
|
||||
@get:Rule val expect: Expect = Expect.create()
|
||||
|
||||
private val portraitShadeInterpolator = LargeScreenPortraitShadeInterpolator()
|
||||
private val splitShadeInterpolator = SplitShadeInterpolator()
|
||||
private val configurationController = FakeConfigurationController()
|
||||
private val impl =
|
||||
LargeScreenShadeInterpolatorImpl(
|
||||
configurationController,
|
||||
context,
|
||||
splitShadeInterpolator,
|
||||
portraitShadeInterpolator
|
||||
)
|
||||
|
||||
@Test
|
||||
fun getBehindScrimAlpha_inSplitShade_usesSplitShadeValue() {
|
||||
setSplitShadeEnabled(true)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getBehindScrimAlpha(fraction) },
|
||||
expected = { fraction -> splitShadeInterpolator.getBehindScrimAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getBehindScrimAlpha_inPortraitShade_usesPortraitShadeValue() {
|
||||
setSplitShadeEnabled(false)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getBehindScrimAlpha(fraction) },
|
||||
expected = { fraction -> portraitShadeInterpolator.getBehindScrimAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNotificationScrimAlpha_inSplitShade_usesSplitShadeValue() {
|
||||
setSplitShadeEnabled(true)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getNotificationScrimAlpha(fraction) },
|
||||
expected = { fraction -> splitShadeInterpolator.getNotificationScrimAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
@Test
|
||||
fun getNotificationScrimAlpha_inPortraitShade_usesPortraitShadeValue() {
|
||||
setSplitShadeEnabled(false)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getNotificationScrimAlpha(fraction) },
|
||||
expected = { fraction -> portraitShadeInterpolator.getNotificationScrimAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNotificationContentAlpha_inSplitShade_usesSplitShadeValue() {
|
||||
setSplitShadeEnabled(true)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getNotificationContentAlpha(fraction) },
|
||||
expected = { fraction -> splitShadeInterpolator.getNotificationContentAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNotificationContentAlpha_inPortraitShade_usesPortraitShadeValue() {
|
||||
setSplitShadeEnabled(false)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getNotificationContentAlpha(fraction) },
|
||||
expected = { fraction ->
|
||||
portraitShadeInterpolator.getNotificationContentAlpha(fraction)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNotificationFooterAlpha_inSplitShade_usesSplitShadeValue() {
|
||||
setSplitShadeEnabled(true)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getNotificationFooterAlpha(fraction) },
|
||||
expected = { fraction -> splitShadeInterpolator.getNotificationFooterAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
@Test
|
||||
fun getNotificationFooterAlpha_inPortraitShade_usesPortraitShadeValue() {
|
||||
setSplitShadeEnabled(false)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getNotificationFooterAlpha(fraction) },
|
||||
expected = { fraction ->
|
||||
portraitShadeInterpolator.getNotificationFooterAlpha(fraction)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getQsAlpha_inSplitShade_usesSplitShadeValue() {
|
||||
setSplitShadeEnabled(true)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getQsAlpha(fraction) },
|
||||
expected = { fraction -> splitShadeInterpolator.getQsAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
@Test
|
||||
fun getQsAlpha_inPortraitShade_usesPortraitShadeValue() {
|
||||
setSplitShadeEnabled(false)
|
||||
|
||||
assertInterpolation(
|
||||
actual = { fraction -> impl.getQsAlpha(fraction) },
|
||||
expected = { fraction -> portraitShadeInterpolator.getQsAlpha(fraction) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun setSplitShadeEnabled(enabled: Boolean) {
|
||||
overrideResource(R.bool.config_use_split_notification_shade, enabled)
|
||||
configurationController.notifyConfigurationChanged()
|
||||
}
|
||||
|
||||
private fun assertInterpolation(
|
||||
actual: (fraction: Float) -> Float,
|
||||
expected: (fraction: Float) -> Float
|
||||
) {
|
||||
for (i in 0..10) {
|
||||
val fraction = i / 10f
|
||||
expect.that(actual(fraction)).isEqualTo(expected(fraction))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.shade.transition
|
||||
|
||||
class LinearLargeScreenShadeInterpolator : LargeScreenShadeInterpolator {
|
||||
override fun getBehindScrimAlpha(fraction: Float) = fraction
|
||||
override fun getNotificationScrimAlpha(fraction: Float) = fraction
|
||||
override fun getNotificationContentAlpha(fraction: Float) = fraction
|
||||
override fun getNotificationFooterAlpha(fraction: Float) = fraction
|
||||
override fun getQsAlpha(fraction: Float) = fraction
|
||||
}
|
||||
@@ -5,6 +5,8 @@ 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.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.shade.STATE_CLOSED
|
||||
import com.android.systemui.shade.STATE_OPEN
|
||||
import com.android.systemui.shade.STATE_OPENING
|
||||
@@ -30,6 +32,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
|
||||
@Mock private lateinit var dumpManager: DumpManager
|
||||
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
|
||||
@Mock private lateinit var headsUpManager: HeadsUpManager
|
||||
@Mock private lateinit var featureFlags: FeatureFlags
|
||||
private val configurationController = FakeConfigurationController()
|
||||
|
||||
private lateinit var controller: ScrimShadeTransitionController
|
||||
@@ -45,7 +48,8 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
|
||||
scrimController,
|
||||
context.resources,
|
||||
statusBarStateController,
|
||||
headsUpManager)
|
||||
headsUpManager,
|
||||
featureFlags)
|
||||
|
||||
controller.onPanelStateChanged(STATE_OPENING)
|
||||
}
|
||||
@@ -106,6 +110,19 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
|
||||
verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPanelExpansionChanged_inSplitShade_flagTrue_setsFractionEqualToEventFraction() {
|
||||
whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(true)
|
||||
whenever(statusBarStateController.currentOrUpcomingState)
|
||||
.thenReturn(StatusBarState.SHADE)
|
||||
setSplitShadeEnabled(true)
|
||||
|
||||
controller.onPanelExpansionChanged(EXPANSION_EVENT)
|
||||
|
||||
verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onPanelExpansionChanged_inSplitShade_onKeyguard_setsFractionEqualToEventFraction() {
|
||||
whenever(statusBarStateController.currentOrUpcomingState)
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
|
||||
import com.android.systemui.statusbar.StatusBarState
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
|
||||
import com.android.systemui.util.mockito.mock
|
||||
@@ -39,6 +41,8 @@ class AmbientStateTest : SysuiTestCase() {
|
||||
private val sectionProvider = StackScrollAlgorithm.SectionProvider { _, _ -> false }
|
||||
private val bypassController = StackScrollAlgorithm.BypassController { false }
|
||||
private val statusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>()
|
||||
private val largeScreenShadeInterpolator = mock<LargeScreenShadeInterpolator>()
|
||||
private val featureFlags = mock<FeatureFlags>()
|
||||
|
||||
private lateinit var sut: AmbientState
|
||||
|
||||
@@ -51,6 +55,8 @@ class AmbientStateTest : SysuiTestCase() {
|
||||
sectionProvider,
|
||||
bypassController,
|
||||
statusBarKeyguardViewManager,
|
||||
largeScreenShadeInterpolator,
|
||||
featureFlags
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.ShadeInterpolation
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
|
||||
import com.android.systemui.statusbar.NotificationShelf
|
||||
import com.android.systemui.statusbar.StatusBarIconView
|
||||
import com.android.systemui.statusbar.notification.LegacySourceType
|
||||
@@ -21,7 +24,9 @@ import junit.framework.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
/**
|
||||
@@ -32,6 +37,9 @@ import org.mockito.Mockito.`when` as whenever
|
||||
@RunWithLooper
|
||||
class NotificationShelfTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var largeScreenShadeInterpolator: LargeScreenShadeInterpolator
|
||||
@Mock private lateinit var flags: FeatureFlags
|
||||
|
||||
private val shelf = NotificationShelf(
|
||||
context,
|
||||
/* attrs */ null,
|
||||
@@ -50,8 +58,12 @@ class NotificationShelfTest : SysuiTestCase() {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
whenever(ambientState.largeScreenShadeInterpolator).thenReturn(largeScreenShadeInterpolator)
|
||||
whenever(ambientState.featureFlags).thenReturn(flags)
|
||||
shelf.bind(ambientState, /* hostLayoutController */ hostLayoutController)
|
||||
shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5)
|
||||
whenever(ambientState.isSmallScreen).thenReturn(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -295,7 +307,35 @@ class NotificationShelfTest : SysuiTestCase() {
|
||||
fun updateState_expansionChanging_shelfAlphaUpdated() {
|
||||
updateState_expansionChanging_shelfAlphaUpdated(
|
||||
expansionFraction = 0.6f,
|
||||
expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f)
|
||||
expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_flagTrue_largeScreen_expansionChanging_shelfAlphaUpdated_largeScreenValue() {
|
||||
val expansionFraction = 0.6f
|
||||
whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(true)
|
||||
whenever(ambientState.isSmallScreen).thenReturn(false)
|
||||
whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
|
||||
.thenReturn(0.123f)
|
||||
|
||||
updateState_expansionChanging_shelfAlphaUpdated(
|
||||
expansionFraction = expansionFraction,
|
||||
expectedAlpha = 0.123f
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_flagFalse_largeScreen_expansionChanging_shelfAlphaUpdated_standardValue() {
|
||||
val expansionFraction = 0.6f
|
||||
whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(false)
|
||||
whenever(ambientState.isSmallScreen).thenReturn(false)
|
||||
whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
|
||||
.thenReturn(0.123f)
|
||||
|
||||
updateState_expansionChanging_shelfAlphaUpdated(
|
||||
expansionFraction = expansionFraction,
|
||||
expectedAlpha = ShadeInterpolation.getContentAlpha(expansionFraction)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -305,7 +345,17 @@ class NotificationShelfTest : SysuiTestCase() {
|
||||
|
||||
updateState_expansionChanging_shelfAlphaUpdated(
|
||||
expansionFraction = 0.95f,
|
||||
expectedAlpha = aboutToShowBouncerProgress(0.95f)
|
||||
expectedAlpha = aboutToShowBouncerProgress(0.95f),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateState_largeScreen_expansionChangingWhileBouncerInTransit_bouncerInterpolatorUsed() {
|
||||
whenever(ambientState.isBouncerInTransit).thenReturn(true)
|
||||
|
||||
updateState_expansionChanging_shelfAlphaUpdated(
|
||||
expansionFraction = 0.95f,
|
||||
expectedAlpha = aboutToShowBouncerProgress(0.95f),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.shade.transition.ShadeTransitionController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
||||
@@ -136,7 +135,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
||||
@Mock private StackStateLogger mStackLogger;
|
||||
@Mock private NotificationStackScrollLogger mLogger;
|
||||
@Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||
@Mock private ShadeTransitionController mShadeTransitionController;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
@Mock private NotificationTargetsHelper mNotificationTargetsHelper;
|
||||
@Mock private SecureSettings mSecureSettings;
|
||||
@@ -184,7 +182,6 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
||||
mNotifPipelineFlags,
|
||||
mNotifCollection,
|
||||
mLockscreenShadeTransitionController,
|
||||
mShadeTransitionController,
|
||||
mUiEventLogger,
|
||||
mRemoteInputManager,
|
||||
mVisibilityLocationProviderDelegator,
|
||||
|
||||
@@ -68,7 +68,9 @@ import com.android.systemui.ExpandHelper;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.shade.ShadeController;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.EmptyShadeView;
|
||||
import com.android.systemui.statusbar.NotificationShelf;
|
||||
import com.android.systemui.statusbar.NotificationShelfController;
|
||||
@@ -129,6 +131,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
||||
@Mock private NotificationShelf mNotificationShelf;
|
||||
@Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
@Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
@@ -142,7 +146,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
||||
mDumpManager,
|
||||
mNotificationSectionsManager,
|
||||
mBypassController,
|
||||
mStatusBarKeyguardViewManager));
|
||||
mStatusBarKeyguardViewManager,
|
||||
mLargeScreenShadeInterpolator,
|
||||
mFeatureFlags
|
||||
));
|
||||
|
||||
// Inject dependencies before initializing the layout
|
||||
mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState);
|
||||
|
||||
@@ -8,6 +8,9 @@ import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
|
||||
import com.android.systemui.statusbar.EmptyShadeView
|
||||
import com.android.systemui.statusbar.NotificationShelf
|
||||
import com.android.systemui.statusbar.StatusBarState
|
||||
@@ -15,11 +18,13 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.google.common.truth.Expect
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import junit.framework.Assert.assertEquals
|
||||
import junit.framework.Assert.assertFalse
|
||||
import junit.framework.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.eq
|
||||
@@ -30,12 +35,19 @@ import org.mockito.Mockito.`when` as whenever
|
||||
@SmallTest
|
||||
class StackScrollAlgorithmTest : SysuiTestCase() {
|
||||
|
||||
|
||||
@JvmField @Rule
|
||||
var expect: Expect = Expect.create()
|
||||
|
||||
private val largeScreenShadeInterpolator = mock<LargeScreenShadeInterpolator>()
|
||||
|
||||
private val hostView = FrameLayout(context)
|
||||
private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
|
||||
private val notificationRow = mock<ExpandableNotificationRow>()
|
||||
private val dumpManager = mock<DumpManager>()
|
||||
private val mStatusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>()
|
||||
private val notificationShelf = mock<NotificationShelf>()
|
||||
private val featureFlags = mock<FeatureFlags>()
|
||||
private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
|
||||
layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
|
||||
}
|
||||
@@ -44,8 +56,10 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
|
||||
dumpManager,
|
||||
/* sectionProvider */ { _, _ -> false },
|
||||
/* bypassController */ { false },
|
||||
mStatusBarKeyguardViewManager
|
||||
)
|
||||
mStatusBarKeyguardViewManager,
|
||||
largeScreenShadeInterpolator,
|
||||
featureFlags,
|
||||
)
|
||||
|
||||
private val testableResources = mContext.getOrCreateTestableResources()
|
||||
|
||||
@@ -59,6 +73,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
|
||||
fun setUp() {
|
||||
whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
|
||||
whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
|
||||
ambientState.isSmallScreen = true
|
||||
|
||||
hostView.addView(notificationRow)
|
||||
}
|
||||
@@ -145,11 +160,46 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetViewStates_expansionChangingWhileBouncerInTransit_notificationAlphaUpdated() {
|
||||
fun resetViewStates_flagTrue_largeScreen_expansionChanging_alphaUpdated_largeScreenValue() {
|
||||
val expansionFraction = 0.6f
|
||||
val surfaceAlpha = 123f
|
||||
ambientState.isSmallScreen = false
|
||||
whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(true)
|
||||
whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
|
||||
whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
|
||||
.thenReturn(surfaceAlpha)
|
||||
|
||||
resetViewStates_expansionChanging_notificationAlphaUpdated(
|
||||
expansionFraction = expansionFraction,
|
||||
expectedAlpha = surfaceAlpha,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetViewStates_flagFalse_largeScreen_expansionChanging_alphaUpdated_standardValue() {
|
||||
val expansionFraction = 0.6f
|
||||
val surfaceAlpha = 123f
|
||||
ambientState.isSmallScreen = false
|
||||
whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(false)
|
||||
whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
|
||||
whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
|
||||
.thenReturn(surfaceAlpha)
|
||||
|
||||
resetViewStates_expansionChanging_notificationAlphaUpdated(
|
||||
expansionFraction = expansionFraction,
|
||||
expectedAlpha = getContentAlpha(expansionFraction),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun expansionChanging_largeScreen_bouncerInTransit_alphaUpdated_bouncerValues() {
|
||||
ambientState.isSmallScreen = false
|
||||
whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(true)
|
||||
resetViewStates_expansionChanging_notificationAlphaUpdated(
|
||||
expansionFraction = 0.95f,
|
||||
expectedAlpha = aboutToShowBouncerProgress(0.95f)
|
||||
expectedAlpha = aboutToShowBouncerProgress(0.95f),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -696,7 +746,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
|
||||
|
||||
private fun resetViewStates_expansionChanging_notificationAlphaUpdated(
|
||||
expansionFraction: Float,
|
||||
expectedAlpha: Float
|
||||
expectedAlpha: Float,
|
||||
) {
|
||||
ambientState.isExpansionChanging = true
|
||||
ambientState.expansionFraction = expansionFraction
|
||||
@@ -704,7 +754,7 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
|
||||
|
||||
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
|
||||
|
||||
assertThat(notificationRow.viewState.alpha).isEqualTo(expectedAlpha)
|
||||
expect.that(notificationRow.viewState.alpha).isEqualTo(expectedAlpha)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ import static com.android.systemui.statusbar.phone.ScrimState.SHADE_LOCKED;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
@@ -41,6 +39,8 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.app.AlarmManager;
|
||||
import android.graphics.Color;
|
||||
@@ -59,6 +59,8 @@ import com.android.systemui.DejankUtils;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.animation.ShadeInterpolation;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
|
||||
@@ -67,6 +69,8 @@ import com.android.systemui.keyguard.shared.model.TransitionState;
|
||||
import com.android.systemui.keyguard.shared.model.TransitionStep;
|
||||
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
|
||||
import com.android.systemui.scrim.ScrimView;
|
||||
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
|
||||
import com.android.systemui.shade.transition.LinearLargeScreenShadeInterpolator;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.policy.FakeConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
@@ -104,6 +108,8 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
|
||||
private final FakeConfigurationController mConfigurationController =
|
||||
new FakeConfigurationController();
|
||||
private final LargeScreenShadeInterpolator
|
||||
mLinearLargeScreenShadeInterpolator = new LinearLargeScreenShadeInterpolator();
|
||||
|
||||
private ScrimController mScrimController;
|
||||
private ScrimView mScrimBehind;
|
||||
@@ -133,6 +139,7 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
// TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
|
||||
// event-dispatch-on-registration pattern caused some of these unit tests to fail.)
|
||||
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
|
||||
private static class AnimatorListener implements Animator.AnimatorListener {
|
||||
private int mNumStarts;
|
||||
@@ -245,17 +252,26 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
when(mPrimaryBouncerToGoneTransitionViewModel.getScrimBehindAlpha())
|
||||
.thenReturn(emptyFlow());
|
||||
|
||||
mScrimController = new ScrimController(mLightBarController,
|
||||
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
|
||||
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
|
||||
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
|
||||
mScrimController = new ScrimController(
|
||||
mLightBarController,
|
||||
mDozeParameters,
|
||||
mAlarmManager,
|
||||
mKeyguardStateController,
|
||||
mDelayedWakeLockBuilder,
|
||||
new FakeHandler(mLooper.getLooper()),
|
||||
mKeyguardUpdateMonitor,
|
||||
mDockManager,
|
||||
mConfigurationController,
|
||||
new FakeExecutor(new FakeSystemClock()),
|
||||
mScreenOffAnimationController,
|
||||
mKeyguardUnlockAnimationController,
|
||||
mStatusBarKeyguardViewManager,
|
||||
mPrimaryBouncerToGoneTransitionViewModel,
|
||||
mKeyguardTransitionInteractor,
|
||||
mSysuiStatusBarStateController,
|
||||
mMainDispatcher);
|
||||
mMainDispatcher,
|
||||
mLinearLargeScreenShadeInterpolator,
|
||||
mFeatureFlags);
|
||||
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
|
||||
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
|
||||
mScrimController.setAnimatorListener(mAnimatorListener);
|
||||
@@ -653,7 +669,81 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToUnlocked() {
|
||||
public void transitionToUnlocked_clippedQs() {
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
mScrimController.setRawPanelExpansionFraction(0f);
|
||||
mScrimController.transitionTo(ScrimState.UNLOCKED);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimTinted(Map.of(
|
||||
mNotificationsScrim, false,
|
||||
mScrimInFront, false,
|
||||
mScrimBehind, true
|
||||
));
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, TRANSPARENT,
|
||||
mScrimBehind, OPAQUE));
|
||||
|
||||
mScrimController.setRawPanelExpansionFraction(0.25f);
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, SEMI_TRANSPARENT,
|
||||
mScrimBehind, OPAQUE));
|
||||
|
||||
mScrimController.setRawPanelExpansionFraction(0.5f);
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, OPAQUE,
|
||||
mScrimBehind, OPAQUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transitionToUnlocked_nonClippedQs_flagTrue_followsLargeScreensInterpolator() {
|
||||
when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(true);
|
||||
mScrimController.setClipsQsScrim(false);
|
||||
mScrimController.setRawPanelExpansionFraction(0f);
|
||||
mScrimController.transitionTo(ScrimState.UNLOCKED);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
assertScrimTinted(Map.of(
|
||||
mNotificationsScrim, false,
|
||||
mScrimInFront, false,
|
||||
mScrimBehind, true
|
||||
));
|
||||
// The large screens interpolator used in this test is a linear one, just for tests.
|
||||
// Assertions below are based on this assumption, and that the code uses that interpolator
|
||||
// when on a large screen (QS not clipped).
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, TRANSPARENT,
|
||||
mScrimBehind, TRANSPARENT));
|
||||
|
||||
mScrimController.setRawPanelExpansionFraction(0.5f);
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, SEMI_TRANSPARENT,
|
||||
mScrimBehind, SEMI_TRANSPARENT));
|
||||
|
||||
mScrimController.setRawPanelExpansionFraction(0.99f);
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, SEMI_TRANSPARENT,
|
||||
mScrimBehind, SEMI_TRANSPARENT));
|
||||
|
||||
mScrimController.setRawPanelExpansionFraction(1f);
|
||||
assertScrimAlpha(Map.of(
|
||||
mScrimInFront, TRANSPARENT,
|
||||
mNotificationsScrim, OPAQUE,
|
||||
mScrimBehind, OPAQUE));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void transitionToUnlocked_nonClippedQs_flagFalse() {
|
||||
when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
|
||||
.thenReturn(false);
|
||||
mScrimController.setClipsQsScrim(false);
|
||||
mScrimController.setRawPanelExpansionFraction(0f);
|
||||
mScrimController.transitionTo(ScrimState.UNLOCKED);
|
||||
@@ -691,7 +781,6 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
mScrimBehind, OPAQUE));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void scrimStateCallback() {
|
||||
mScrimController.transitionTo(ScrimState.UNLOCKED);
|
||||
@@ -879,17 +968,26 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
// GIVEN display does NOT need blanking
|
||||
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
|
||||
|
||||
mScrimController = new ScrimController(mLightBarController,
|
||||
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
|
||||
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
|
||||
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
|
||||
mScrimController = new ScrimController(
|
||||
mLightBarController,
|
||||
mDozeParameters,
|
||||
mAlarmManager,
|
||||
mKeyguardStateController,
|
||||
mDelayedWakeLockBuilder,
|
||||
new FakeHandler(mLooper.getLooper()),
|
||||
mKeyguardUpdateMonitor,
|
||||
mDockManager,
|
||||
mConfigurationController,
|
||||
new FakeExecutor(new FakeSystemClock()),
|
||||
mScreenOffAnimationController,
|
||||
mKeyguardUnlockAnimationController,
|
||||
mStatusBarKeyguardViewManager,
|
||||
mPrimaryBouncerToGoneTransitionViewModel,
|
||||
mKeyguardTransitionInteractor,
|
||||
mSysuiStatusBarStateController,
|
||||
mMainDispatcher);
|
||||
mMainDispatcher,
|
||||
mLinearLargeScreenShadeInterpolator,
|
||||
mFeatureFlags);
|
||||
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
|
||||
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
|
||||
mScrimController.setAnimatorListener(mAnimatorListener);
|
||||
|
||||
Reference in New Issue
Block a user