Merge "Allow swipe up on unlocked dream." into tm-qpr-dev am: 5ef8b6f81c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21061907

Change-Id: Ieaf67f1de73d6d2a13319cb9a8ed124f8c25a8d8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Bryce Lee
2023-01-27 17:20:06 +00:00
committed by Automerger Merge Worker
13 changed files with 609 additions and 22 deletions

View File

@@ -37,8 +37,10 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.complication.ComplicationHostViewController; import com.android.systemui.dreams.complication.ComplicationHostViewController;
import com.android.systemui.dreams.dagger.DreamOverlayComponent; import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.dagger.DreamOverlayModule; import com.android.systemui.dreams.dagger.DreamOverlayModule;
import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -82,6 +84,22 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
private long mJitterStartTimeMillis; private long mJitterStartTimeMillis;
private boolean mBouncerAnimating; private boolean mBouncerAnimating;
private boolean mWakingUpFromSwipe;
private final BouncerlessScrimController mBouncerlessScrimController;
private final BouncerlessScrimController.Callback mBouncerlessExpansionCallback =
new BouncerlessScrimController.Callback() {
@Override
public void onExpansion(ShadeExpansionChangeEvent event) {
updateTransitionState(event.getFraction());
}
@Override
public void onWakeup() {
mWakingUpFromSwipe = true;
}
};
private final PrimaryBouncerExpansionCallback private final PrimaryBouncerExpansionCallback
mBouncerExpansionCallback = mBouncerExpansionCallback =
@@ -156,7 +174,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
@Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter, @Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter,
PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor, PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
DreamOverlayAnimationsController animationsController, DreamOverlayAnimationsController animationsController,
DreamOverlayStateController stateController) { DreamOverlayStateController stateController,
BouncerlessScrimController bouncerlessScrimController) {
super(containerView); super(containerView);
mDreamOverlayContentView = contentView; mDreamOverlayContentView = contentView;
mStatusBarViewController = statusBarViewController; mStatusBarViewController = statusBarViewController;
@@ -164,6 +183,9 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
mDreamOverlayAnimationsController = animationsController; mDreamOverlayAnimationsController = animationsController;
mStateController = stateController; mStateController = stateController;
mBouncerlessScrimController = bouncerlessScrimController;
mBouncerlessScrimController.addCallback(mBouncerlessExpansionCallback);
mComplicationHostViewController = complicationHostViewController; mComplicationHostViewController = complicationHostViewController;
mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize( mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
R.dimen.dream_overlay_y_offset); R.dimen.dream_overlay_y_offset);
@@ -190,6 +212,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
@Override @Override
protected void onViewAttached() { protected void onViewAttached() {
mWakingUpFromSwipe = false;
mJitterStartTimeMillis = System.currentTimeMillis(); mJitterStartTimeMillis = System.currentTimeMillis();
mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval); mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(mBouncerExpansionCallback); mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(mBouncerExpansionCallback);
@@ -278,6 +301,13 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
*/ */
public void wakeUp(@NonNull Runnable onAnimationEnd, public void wakeUp(@NonNull Runnable onAnimationEnd,
@NonNull DelayableExecutor callbackExecutor) { @NonNull DelayableExecutor callbackExecutor) {
// When swiping causes wakeup, do not run any animations as the dream should exit as soon
// as possible.
if (mWakingUpFromSwipe) {
onAnimationEnd.run();
return;
}
mDreamOverlayAnimationsController.wakeUp(onAnimationEnd, callbackExecutor); mDreamOverlayAnimationsController.wakeUp(onAnimationEnd, callbackExecutor);
} }
} }

View File

@@ -28,6 +28,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayNotificationCountProvider; import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
import com.android.systemui.dreams.DreamOverlayService; import com.android.systemui.dreams.DreamOverlayService;
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule; import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule;
import java.util.Optional; import java.util.Optional;
@@ -42,6 +43,7 @@ import dagger.Provides;
@Module(includes = { @Module(includes = {
RegisteredComplicationsModule.class, RegisteredComplicationsModule.class,
LowLightDreamModule.class, LowLightDreamModule.class,
ScrimModule.class
}, },
subcomponents = { subcomponents = {
DreamOverlayComponent.class, DreamOverlayComponent.class,

View File

@@ -36,11 +36,12 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dreams.touch.scrim.ScrimController;
import com.android.systemui.dreams.touch.scrim.ScrimManager;
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants; import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.animation.FlingAnimationUtils;
import java.util.Optional; import java.util.Optional;
@@ -78,7 +79,8 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationShadeWindowController mNotificationShadeWindowController;
private final float mBouncerZoneScreenPercentage; private final float mBouncerZoneScreenPercentage;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final ScrimManager mScrimManager;
private ScrimController mCurrentScrimController;
private float mCurrentExpansion; private float mCurrentExpansion;
private final Optional<CentralSurfaces> mCentralSurfaces; private final Optional<CentralSurfaces> mCentralSurfaces;
@@ -90,6 +92,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
private final DisplayMetrics mDisplayMetrics; private final DisplayMetrics mDisplayMetrics;
private Boolean mCapture; private Boolean mCapture;
private Boolean mExpanded;
private boolean mBouncerInitiallyShowing; private boolean mBouncerInitiallyShowing;
@@ -101,6 +104,17 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
private final UiEventLogger mUiEventLogger; private final UiEventLogger mUiEventLogger;
private final ScrimManager.Callback mScrimManagerCallback = new ScrimManager.Callback() {
@Override
public void onScrimControllerChanged(ScrimController controller) {
if (mCurrentScrimController != null) {
mCurrentScrimController.reset();
}
mCurrentScrimController = controller;
}
};
private final GestureDetector.OnGestureListener mOnGestureListener = private final GestureDetector.OnGestureListener mOnGestureListener =
new GestureDetector.SimpleOnGestureListener() { new GestureDetector.SimpleOnGestureListener() {
@Override @Override
@@ -115,8 +129,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
.orElse(false); .orElse(false);
if (mCapture) { if (mCapture) {
// reset expanding
mExpanded = false;
// Since the user is dragging the bouncer up, set scrimmed to false. // Since the user is dragging the bouncer up, set scrimmed to false.
mStatusBarKeyguardViewManager.showPrimaryBouncer(false); mCurrentScrimController.show();
} }
} }
@@ -157,10 +173,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
ShadeExpansionChangeEvent event = ShadeExpansionChangeEvent event =
new ShadeExpansionChangeEvent( new ShadeExpansionChangeEvent(
/* fraction= */ mCurrentExpansion, /* fraction= */ mCurrentExpansion,
/* expanded= */ false, /* expanded= */ mExpanded,
/* tracking= */ true, /* tracking= */ true,
/* dragDownPxAmount= */ dragDownAmount); /* dragDownPxAmount= */ dragDownAmount);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(event); mCurrentScrimController.expand(event);
} }
@@ -187,7 +203,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
@Inject @Inject
public BouncerSwipeTouchHandler( public BouncerSwipeTouchHandler(
DisplayMetrics displayMetrics, DisplayMetrics displayMetrics,
StatusBarKeyguardViewManager statusBarKeyguardViewManager, ScrimManager scrimManager,
Optional<CentralSurfaces> centralSurfaces, Optional<CentralSurfaces> centralSurfaces,
NotificationShadeWindowController notificationShadeWindowController, NotificationShadeWindowController notificationShadeWindowController,
ValueAnimatorCreator valueAnimatorCreator, ValueAnimatorCreator valueAnimatorCreator,
@@ -200,7 +216,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
UiEventLogger uiEventLogger) { UiEventLogger uiEventLogger) {
mDisplayMetrics = displayMetrics; mDisplayMetrics = displayMetrics;
mCentralSurfaces = centralSurfaces; mCentralSurfaces = centralSurfaces;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mScrimManager = scrimManager;
mNotificationShadeWindowController = notificationShadeWindowController; mNotificationShadeWindowController = notificationShadeWindowController;
mBouncerZoneScreenPercentage = swipeRegionPercentage; mBouncerZoneScreenPercentage = swipeRegionPercentage;
mFlingAnimationUtils = flingAnimationUtils; mFlingAnimationUtils = flingAnimationUtils;
@@ -234,9 +250,12 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
mTouchSession = session; mTouchSession = session;
mVelocityTracker.clear(); mVelocityTracker.clear();
mNotificationShadeWindowController.setForcePluginOpen(true, this); mNotificationShadeWindowController.setForcePluginOpen(true, this);
mScrimManager.addCallback(mScrimManagerCallback);
mCurrentScrimController = mScrimManager.getCurrentController();
session.registerCallback(() -> { session.registerCallback(() -> {
mVelocityTracker.recycle(); mVelocityTracker.recycle();
mScrimManager.removeCallback(mScrimManagerCallback);
mCapture = null; mCapture = null;
mNotificationShadeWindowController.setForcePluginOpen(false, this); mNotificationShadeWindowController.setForcePluginOpen(false, this);
}); });
@@ -273,9 +292,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
final float velocityVector = final float velocityVector =
(float) Math.hypot(horizontalVelocity, verticalVelocity); (float) Math.hypot(horizontalVelocity, verticalVelocity);
final float expansion = flingRevealsOverlay(verticalVelocity, velocityVector) mExpanded = !flingRevealsOverlay(verticalVelocity, velocityVector);
? KeyguardBouncerConstants.EXPANSION_HIDDEN final float expansion = mExpanded
: KeyguardBouncerConstants.EXPANSION_VISIBLE; ? KeyguardBouncerConstants.EXPANSION_VISIBLE
: KeyguardBouncerConstants.EXPANSION_HIDDEN;
// Log the swiping up to show Bouncer event. // Log the swiping up to show Bouncer event.
if (!mBouncerInitiallyShowing if (!mBouncerInitiallyShowing
@@ -286,7 +306,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
flingToExpansion(verticalVelocity, expansion); flingToExpansion(verticalVelocity, expansion);
if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) { if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
mStatusBarKeyguardViewManager.reset(false); mCurrentScrimController.reset();
} }
break; break;
default: default:

View File

@@ -0,0 +1,49 @@
/*
* 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.dreams.touch.scrim;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import javax.inject.Inject;
/**
* Implementation for handling swipe movements on the overlay when the keyguard is present.
*/
public class BouncerScrimController implements ScrimController {
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
BouncerScrimController(StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
}
@Override
public void show() {
mStatusBarKeyguardViewManager.showBouncer(false);
}
@Override
public void expand(ShadeExpansionChangeEvent event) {
mStatusBarKeyguardViewManager.onPanelExpansionChanged(event);
}
@Override
public void reset() {
mStatusBarKeyguardViewManager.reset(false);
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.dreams.touch.scrim;
import android.os.PowerManager;
import android.os.SystemClock;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.unfold.util.CallbackController;
import java.util.HashSet;
import java.util.concurrent.Executor;
import javax.inject.Inject;
/**
* {@link BouncerlessScrimController} handles scrim progression when no keyguard is set. When
* fully expanded, the controller dismisses the dream.
*/
@SysUISingleton
public class BouncerlessScrimController implements ScrimController,
CallbackController<BouncerlessScrimController.Callback> {
private static final String TAG = "BLScrimController";
/**
* {@link Callback} allows {@link BouncerlessScrimController} clients to be informed of
* expansion progression and wakeup
*/
public interface Callback {
/**
* Invoked when there is a change to the scrim expansion.
*/
void onExpansion(ShadeExpansionChangeEvent event);
/**
* Invoked after {@link BouncerlessScrimController} has started waking up the device.
*/
void onWakeup();
}
private final Executor mExecutor;
private final PowerManager mPowerManager;
@Override
public void addCallback(Callback listener) {
mExecutor.execute(() -> mCallbacks.add(listener));
}
@Override
public void removeCallback(Callback listener) {
mExecutor.execute(() -> mCallbacks.remove(listener));
}
private final HashSet<Callback> mCallbacks;
@Inject
public BouncerlessScrimController(@Main Executor executor,
PowerManager powerManager) {
mExecutor = executor;
mPowerManager = powerManager;
mCallbacks = new HashSet<>();
}
@Override
public void expand(ShadeExpansionChangeEvent event) {
if (event.getExpanded()) {
mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:SwipeUp");
mExecutor.execute(() -> mCallbacks.forEach(callback -> callback.onWakeup()));
} else {
mExecutor.execute(() -> mCallbacks.forEach(callback -> callback.onExpansion(event)));
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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.dreams.touch.scrim;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
/**
* {@link ScrimController} provides an interface for the different consumers of scrolling/expansion
* events over the dream.
*/
public interface ScrimController {
/**
* Called at the start of expansion before any expansion amount updates.
*/
default void show() {
}
/**
* Called for every expansion update.
* @param event {@link ShadeExpansionChangeEvent} detailing the change.
*/
default void expand(ShadeExpansionChangeEvent event) {
}
/**
* Called at the end of the movement.
*/
default void reset() {
}
}

View File

@@ -0,0 +1,112 @@
/*
* 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.dreams.touch.scrim;
import static com.android.systemui.dreams.touch.scrim.dagger.ScrimModule.BOUNCERLESS_SCRIM_CONTROLLER;
import static com.android.systemui.dreams.touch.scrim.dagger.ScrimModule.BOUNCER_SCRIM_CONTROLLER;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.util.HashSet;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
/**
* {@link ScrimManager} helps manage multiple {@link ScrimController} instances, specifying the
* appropriate one to use at the current moment and managing the handoff between controllers.
*/
public class ScrimManager {
private final ScrimController mBouncerScrimController;
private final ScrimController mBouncerlessScrimController;
private final KeyguardStateController mKeyguardStateController;
private final Executor mExecutor;
private ScrimController mCurrentController;
private final HashSet<Callback> mCallbacks;
/**
* Interface implemented for receiving updates to the active {@link ScrimController}.
*/
public interface Callback {
/**
* Invoked when the controller changes.
* @param controller The currently active {@link ScrimController}.
*/
void onScrimControllerChanged(ScrimController controller);
}
private final KeyguardStateController.Callback mKeyguardStateCallback =
new KeyguardStateController.Callback() {
@Override
public void onKeyguardShowingChanged() {
mExecutor.execute(() -> updateController());
}
};
@Inject
ScrimManager(@Main Executor executor,
@Named(BOUNCER_SCRIM_CONTROLLER) ScrimController bouncerScrimController,
@Named(BOUNCERLESS_SCRIM_CONTROLLER)ScrimController bouncerlessScrimController,
KeyguardStateController keyguardStateController) {
mExecutor = executor;
mCallbacks = new HashSet<>();
mBouncerlessScrimController = bouncerlessScrimController;
mBouncerScrimController = bouncerScrimController;
mKeyguardStateController = keyguardStateController;
mKeyguardStateController.addCallback(mKeyguardStateCallback);
updateController();
}
private void updateController() {
final ScrimController existingController = mCurrentController;
mCurrentController = mKeyguardStateController.canDismissLockScreen()
? mBouncerlessScrimController
: mBouncerScrimController;
if (existingController == mCurrentController) {
return;
}
mCallbacks.forEach(callback -> callback.onScrimControllerChanged(mCurrentController));
}
/**
* Adds a {@link Callback} to receive future changes to the active {@link ScrimController}.
*/
public void addCallback(Callback callback) {
mExecutor.execute(() -> mCallbacks.add(callback));
}
/**
* Removes the {@link Callback} from receiving further updates.
*/
public void removeCallback(Callback callback) {
mExecutor.execute(() -> mCallbacks.remove(callback));
}
/**
* Returns the currently get {@link ScrimController}.
* @return
*/
public ScrimController getCurrentController() {
return mCurrentController;
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.dreams.touch.scrim.dagger;
import com.android.systemui.dreams.touch.scrim.BouncerScrimController;
import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
import com.android.systemui.dreams.touch.scrim.ScrimController;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
/**
* Module for scrim related dependencies.
*/
@Module
public interface ScrimModule {
String BOUNCERLESS_SCRIM_CONTROLLER = "bouncerless_scrim_controller";
String BOUNCER_SCRIM_CONTROLLER = "bouncer_scrim_controller";
/** */
@Provides
@Named(BOUNCERLESS_SCRIM_CONTROLLER)
static ScrimController providesBouncerlessScrimController(
BouncerlessScrimController controller) {
return controller;
}
/** */
@Provides
@Named(BOUNCER_SCRIM_CONTROLLER)
static ScrimController providesBouncerScrimController(
BouncerScrimController controller) {
return controller;
}
}

View File

@@ -77,6 +77,12 @@ public class CrossFadeHelper {
*/ */
public static void fadeOut(View view, float fadeOutAmount, boolean remap) { public static void fadeOut(View view, float fadeOutAmount, boolean remap) {
view.animate().cancel(); view.animate().cancel();
// Don't fade out if already not visible.
if (view.getAlpha() == 0.0f) {
return;
}
if (fadeOutAmount == 1.0f && view.getVisibility() != View.GONE) { if (fadeOutAmount == 1.0f && view.getVisibility() != View.GONE) {
view.setVisibility(View.INVISIBLE); view.setVisibility(View.INVISIBLE);
} else if (view.getVisibility() == View.INVISIBLE) { } else if (view.getVisibility() == View.INVISIBLE) {

View File

@@ -36,6 +36,7 @@ import androidx.test.filters.SmallTest;
import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.complication.ComplicationHostViewController; import com.android.systemui.dreams.complication.ComplicationHostViewController;
import com.android.systemui.dreams.touch.scrim.BouncerlessScrimController;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.statusbar.BlurUtils;
@@ -87,6 +88,9 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
@Mock @Mock
DreamOverlayAnimationsController mAnimationsController; DreamOverlayAnimationsController mAnimationsController;
@Mock
BouncerlessScrimController mBouncerlessScrimController;
@Mock @Mock
DreamOverlayStateController mStateController; DreamOverlayStateController mStateController;
@@ -113,7 +117,8 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
MILLIS_UNTIL_FULL_JITTER, MILLIS_UNTIL_FULL_JITTER,
mPrimaryBouncerCallbackInteractor, mPrimaryBouncerCallbackInteractor,
mAnimationsController, mAnimationsController,
mStateController); mStateController,
mBouncerlessScrimController);
} }
@Test @Test

View File

@@ -41,12 +41,13 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.touch.scrim.ScrimController;
import com.android.systemui.dreams.touch.scrim.ScrimManager;
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants; import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.shade.ShadeExpansionChangeEvent; import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before; import org.junit.Before;
@@ -63,10 +64,13 @@ import java.util.Optional;
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@Mock @Mock
StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; CentralSurfaces mCentralSurfaces;
@Mock @Mock
CentralSurfaces mCentralSurfaces; ScrimManager mScrimManager;
@Mock
ScrimController mScrimController;
@Mock @Mock
NotificationShadeWindowController mNotificationShadeWindowController; NotificationShadeWindowController mNotificationShadeWindowController;
@@ -111,7 +115,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mTouchHandler = new BouncerSwipeTouchHandler( mTouchHandler = new BouncerSwipeTouchHandler(
mDisplayMetrics, mDisplayMetrics,
mStatusBarKeyguardViewManager, mScrimManager,
Optional.of(mCentralSurfaces), Optional.of(mCentralSurfaces),
mNotificationShadeWindowController, mNotificationShadeWindowController,
mValueAnimatorCreator, mValueAnimatorCreator,
@@ -121,6 +125,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
TOUCH_REGION, TOUCH_REGION,
mUiEventLogger); mUiEventLogger);
when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
when(mCentralSurfaces.isBouncerShowing()).thenReturn(false); when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
when(mCentralSurfaces.getDisplayHeight()).thenReturn((float) SCREEN_HEIGHT_PX); when(mCentralSurfaces.getDisplayHeight()).thenReturn((float) SCREEN_HEIGHT_PX);
when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator); when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
@@ -193,7 +198,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)) assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
.isTrue(); .isTrue();
verify(mStatusBarKeyguardViewManager, never()).onPanelExpansionChanged(any()); verify(mScrimController, never()).expand(any());
} }
/** /**
@@ -220,7 +225,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)) assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
.isTrue(); .isTrue();
verify(mStatusBarKeyguardViewManager, never()).onPanelExpansionChanged(any()); verify(mScrimController, never()).expand(any());
} }
/** /**
@@ -274,12 +279,12 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0); 0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
reset(mStatusBarKeyguardViewManager); reset(mScrimController);
assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)) assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
.isTrue(); .isTrue();
// Ensure only called once // Ensure only called once
verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(any()); verify(mScrimController).expand(any());
final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent; final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent;
final float dragDownAmount = event2.getY() - event1.getY(); final float dragDownAmount = event2.getY() - event1.getY();
@@ -288,7 +293,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
ShadeExpansionChangeEvent event = ShadeExpansionChangeEvent event =
new ShadeExpansionChangeEvent( new ShadeExpansionChangeEvent(
expansion, /* expanded= */ false, /* tracking= */ true, dragDownAmount); expansion, /* expanded= */ false, /* tracking= */ true, dragDownAmount);
verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(event); verify(mScrimController).expand(event);
} }
/** /**

View File

@@ -0,0 +1,78 @@
/*
* 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.dreams.touch.scrim;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import android.os.PowerManager;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class BouncerlessScrimControllerTest extends SysuiTestCase {
@Mock
BouncerlessScrimController.Callback mCallback;
@Mock
PowerManager mPowerManager;
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testWakeupOnSwipeOpen() {
final BouncerlessScrimController scrimController =
new BouncerlessScrimController(mExecutor, mPowerManager);
scrimController.addCallback(mCallback);
scrimController.expand(new ShadeExpansionChangeEvent(.5f, true, false, 0.0f));
mExecutor.runAllReady();
verify(mPowerManager).wakeUp(anyLong(), eq(PowerManager.WAKE_REASON_GESTURE), any());
verify(mCallback).onWakeup();
}
@Test
public void testExpansionPropagation() {
final BouncerlessScrimController scrimController =
new BouncerlessScrimController(mExecutor, mPowerManager);
scrimController.addCallback(mCallback);
final ShadeExpansionChangeEvent expansionEvent =
new ShadeExpansionChangeEvent(0.5f, false, false, 0.0f);
scrimController.expand(expansionEvent);
mExecutor.runAllReady();
verify(mCallback).onExpansion(eq(expansionEvent));
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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.dreams.touch.scrim;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
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;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class ScrimManagerTest extends SysuiTestCase {
@Mock
ScrimController mBouncerlessScrimController;
@Mock
ScrimController mBouncerScrimController;
@Mock
KeyguardStateController mKeyguardStateController;
@Mock
ScrimManager.Callback mCallback;
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testControllerSelection() {
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
final ScrimManager manager = new ScrimManager(mExecutor, mBouncerScrimController,
mBouncerlessScrimController, mKeyguardStateController);
verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
assertThat(manager.getCurrentController()).isEqualTo(mBouncerScrimController);
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
callbackCaptor.getValue().onKeyguardShowingChanged();
mExecutor.runAllReady();
assertThat(manager.getCurrentController()).isEqualTo(mBouncerlessScrimController);
}
@Test
public void testCallback() {
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
ArgumentCaptor<KeyguardStateController.Callback> callbackCaptor =
ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
final ScrimManager manager = new ScrimManager(mExecutor, mBouncerScrimController,
mBouncerlessScrimController, mKeyguardStateController);
verify(mKeyguardStateController).addCallback(callbackCaptor.capture());
manager.addCallback(mCallback);
when(mKeyguardStateController.canDismissLockScreen()).thenReturn(true);
callbackCaptor.getValue().onKeyguardShowingChanged();
mExecutor.runAllReady();
verify(mCallback).onScrimControllerChanged(eq(mBouncerlessScrimController));
}
}