Allow swipe up on unlocked dream.
This change allows users to swipe up on a dream to dismiss when the lock screen can be dismissed without further authentication. Fixes: 227333766 Test: atest BouncerlessScrimControllerTest Test: atest ScrimManagerTest Test: atest BouncerSwipeTouchHandlerTest Change-Id: Ia3d6df9459989f003fad444ff08148666cefc042 Merged-In: Ia3d6df9459989f003fad444ff08148666cefc042
This commit is contained in:
@@ -37,8 +37,10 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dreams.complication.ComplicationHostViewController;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||
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.PrimaryBouncerExpansionCallback;
|
||||
import com.android.systemui.shade.ShadeExpansionChangeEvent;
|
||||
import com.android.systemui.statusbar.BlurUtils;
|
||||
import com.android.systemui.util.ViewController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
@@ -82,6 +84,22 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
private long mJitterStartTimeMillis;
|
||||
|
||||
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
|
||||
mBouncerExpansionCallback =
|
||||
@@ -156,7 +174,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
@Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter,
|
||||
PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
|
||||
DreamOverlayAnimationsController animationsController,
|
||||
DreamOverlayStateController stateController) {
|
||||
DreamOverlayStateController stateController,
|
||||
BouncerlessScrimController bouncerlessScrimController) {
|
||||
super(containerView);
|
||||
mDreamOverlayContentView = contentView;
|
||||
mStatusBarViewController = statusBarViewController;
|
||||
@@ -164,6 +183,9 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
mDreamOverlayAnimationsController = animationsController;
|
||||
mStateController = stateController;
|
||||
|
||||
mBouncerlessScrimController = bouncerlessScrimController;
|
||||
mBouncerlessScrimController.addCallback(mBouncerlessExpansionCallback);
|
||||
|
||||
mComplicationHostViewController = complicationHostViewController;
|
||||
mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
|
||||
R.dimen.dream_overlay_y_offset);
|
||||
@@ -190,6 +212,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
mWakingUpFromSwipe = false;
|
||||
mJitterStartTimeMillis = System.currentTimeMillis();
|
||||
mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
|
||||
mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(mBouncerExpansionCallback);
|
||||
@@ -278,6 +301,13 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
*/
|
||||
public void wakeUp(@NonNull Runnable onAnimationEnd,
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
|
||||
import com.android.systemui.dreams.DreamOverlayService;
|
||||
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
|
||||
import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -42,6 +43,7 @@ import dagger.Provides;
|
||||
@Module(includes = {
|
||||
RegisteredComplicationsModule.class,
|
||||
LowLightDreamModule.class,
|
||||
ScrimModule.class
|
||||
},
|
||||
subcomponents = {
|
||||
DreamOverlayComponent.class,
|
||||
|
||||
@@ -36,11 +36,12 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.logging.UiEvent;
|
||||
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.shade.ShadeExpansionChangeEvent;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||
import com.android.wm.shell.animation.FlingAnimationUtils;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -78,7 +79,8 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
private final NotificationShadeWindowController mNotificationShadeWindowController;
|
||||
private final float mBouncerZoneScreenPercentage;
|
||||
|
||||
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
private final ScrimManager mScrimManager;
|
||||
private ScrimController mCurrentScrimController;
|
||||
private float mCurrentExpansion;
|
||||
private final Optional<CentralSurfaces> mCentralSurfaces;
|
||||
|
||||
@@ -90,6 +92,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
private final DisplayMetrics mDisplayMetrics;
|
||||
|
||||
private Boolean mCapture;
|
||||
private Boolean mExpanded;
|
||||
|
||||
private boolean mBouncerInitiallyShowing;
|
||||
|
||||
@@ -101,6 +104,17 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
|
||||
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 =
|
||||
new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
@@ -115,8 +129,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
.orElse(false);
|
||||
|
||||
if (mCapture) {
|
||||
// reset expanding
|
||||
mExpanded = 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 =
|
||||
new ShadeExpansionChangeEvent(
|
||||
/* fraction= */ mCurrentExpansion,
|
||||
/* expanded= */ false,
|
||||
/* expanded= */ mExpanded,
|
||||
/* tracking= */ true,
|
||||
/* dragDownPxAmount= */ dragDownAmount);
|
||||
mStatusBarKeyguardViewManager.onPanelExpansionChanged(event);
|
||||
mCurrentScrimController.expand(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +203,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
@Inject
|
||||
public BouncerSwipeTouchHandler(
|
||||
DisplayMetrics displayMetrics,
|
||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||
ScrimManager scrimManager,
|
||||
Optional<CentralSurfaces> centralSurfaces,
|
||||
NotificationShadeWindowController notificationShadeWindowController,
|
||||
ValueAnimatorCreator valueAnimatorCreator,
|
||||
@@ -200,7 +216,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
UiEventLogger uiEventLogger) {
|
||||
mDisplayMetrics = displayMetrics;
|
||||
mCentralSurfaces = centralSurfaces;
|
||||
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
|
||||
mScrimManager = scrimManager;
|
||||
mNotificationShadeWindowController = notificationShadeWindowController;
|
||||
mBouncerZoneScreenPercentage = swipeRegionPercentage;
|
||||
mFlingAnimationUtils = flingAnimationUtils;
|
||||
@@ -234,9 +250,12 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
mTouchSession = session;
|
||||
mVelocityTracker.clear();
|
||||
mNotificationShadeWindowController.setForcePluginOpen(true, this);
|
||||
mScrimManager.addCallback(mScrimManagerCallback);
|
||||
mCurrentScrimController = mScrimManager.getCurrentController();
|
||||
|
||||
session.registerCallback(() -> {
|
||||
mVelocityTracker.recycle();
|
||||
mScrimManager.removeCallback(mScrimManagerCallback);
|
||||
mCapture = null;
|
||||
mNotificationShadeWindowController.setForcePluginOpen(false, this);
|
||||
});
|
||||
@@ -273,9 +292,10 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
final float velocityVector =
|
||||
(float) Math.hypot(horizontalVelocity, verticalVelocity);
|
||||
|
||||
final float expansion = flingRevealsOverlay(verticalVelocity, velocityVector)
|
||||
? KeyguardBouncerConstants.EXPANSION_HIDDEN
|
||||
: KeyguardBouncerConstants.EXPANSION_VISIBLE;
|
||||
mExpanded = !flingRevealsOverlay(verticalVelocity, velocityVector);
|
||||
final float expansion = mExpanded
|
||||
? KeyguardBouncerConstants.EXPANSION_VISIBLE
|
||||
: KeyguardBouncerConstants.EXPANSION_HIDDEN;
|
||||
|
||||
// Log the swiping up to show Bouncer event.
|
||||
if (!mBouncerInitiallyShowing
|
||||
@@ -286,7 +306,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
flingToExpansion(verticalVelocity, expansion);
|
||||
|
||||
if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
|
||||
mStatusBarKeyguardViewManager.reset(false);
|
||||
mCurrentScrimController.reset();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,12 @@ public class CrossFadeHelper {
|
||||
*/
|
||||
public static void fadeOut(View view, float fadeOutAmount, boolean remap) {
|
||||
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) {
|
||||
view.setVisibility(View.INVISIBLE);
|
||||
} else if (view.getVisibility() == View.INVISIBLE) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.keyguard.BouncerPanelExpansionCalculator;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
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.PrimaryBouncerExpansionCallback;
|
||||
import com.android.systemui.statusbar.BlurUtils;
|
||||
@@ -87,6 +88,9 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
DreamOverlayAnimationsController mAnimationsController;
|
||||
|
||||
@Mock
|
||||
BouncerlessScrimController mBouncerlessScrimController;
|
||||
|
||||
@Mock
|
||||
DreamOverlayStateController mStateController;
|
||||
|
||||
@@ -113,7 +117,8 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
MILLIS_UNTIL_FULL_JITTER,
|
||||
mPrimaryBouncerCallbackInteractor,
|
||||
mAnimationsController,
|
||||
mStateController);
|
||||
mStateController,
|
||||
mBouncerlessScrimController);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -41,12 +41,13 @@ import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
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.shade.ShadeExpansionChangeEvent;
|
||||
import com.android.systemui.shared.system.InputChannelCompat;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||
import com.android.wm.shell.animation.FlingAnimationUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -63,10 +64,13 @@ import java.util.Optional;
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
CentralSurfaces mCentralSurfaces;
|
||||
|
||||
@Mock
|
||||
CentralSurfaces mCentralSurfaces;
|
||||
ScrimManager mScrimManager;
|
||||
|
||||
@Mock
|
||||
ScrimController mScrimController;
|
||||
|
||||
@Mock
|
||||
NotificationShadeWindowController mNotificationShadeWindowController;
|
||||
@@ -111,7 +115,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTouchHandler = new BouncerSwipeTouchHandler(
|
||||
mDisplayMetrics,
|
||||
mStatusBarKeyguardViewManager,
|
||||
mScrimManager,
|
||||
Optional.of(mCentralSurfaces),
|
||||
mNotificationShadeWindowController,
|
||||
mValueAnimatorCreator,
|
||||
@@ -121,6 +125,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
TOUCH_REGION,
|
||||
mUiEventLogger);
|
||||
|
||||
when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
|
||||
when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
|
||||
when(mCentralSurfaces.getDisplayHeight()).thenReturn((float) SCREEN_HEIGHT_PX);
|
||||
when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
|
||||
@@ -193,7 +198,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
|
||||
.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))
|
||||
.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,
|
||||
0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
|
||||
|
||||
reset(mStatusBarKeyguardViewManager);
|
||||
reset(mScrimController);
|
||||
assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
|
||||
.isTrue();
|
||||
|
||||
// Ensure only called once
|
||||
verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(any());
|
||||
verify(mScrimController).expand(any());
|
||||
|
||||
final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent;
|
||||
final float dragDownAmount = event2.getY() - event1.getY();
|
||||
@@ -288,7 +293,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
ShadeExpansionChangeEvent event =
|
||||
new ShadeExpansionChangeEvent(
|
||||
expansion, /* expanded= */ false, /* tracking= */ true, dragDownAmount);
|
||||
verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(event);
|
||||
verify(mScrimController).expand(event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user