summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java5
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java4
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl44
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceCallback.aidl34
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceTransitionController.aidl24
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISysuiUnlockAnimationController.aidl33
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java49
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt712
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/shared/system/smartspace/SmartspaceTransitionController.kt143
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java5
33 files changed, 924 insertions, 424 deletions
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index da9a92a1f6b4..68c8c3e02a42 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -122,6 +122,11 @@ public interface BcSmartspaceDataPlugin extends Plugin {
* Set or clear device media playing
*/
void setMediaTarget(@Nullable SmartspaceTarget target);
+
+ /**
+ * Get the index of the currently selected page.
+ */
+ int getSelectedPage();
}
/** Interface for launching Intents, which can differ on the lockscreen */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 54c798c7d95d..5d092d02a835 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -55,8 +55,8 @@ public class QuickStepContract {
// See IStartingWindow.aidl
public static final String KEY_EXTRA_SHELL_STARTING_WINDOW =
"extra_shell_starting_window";
- // See ISmartspaceTransitionController.aidl
- public static final String KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER = "smartspace_transition";
+ // See ISysuiUnlockAnimationController.aidl
+ public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation";
// See IRecentTasks.aidl
public static final String KEY_EXTRA_RECENT_TASKS = "recent_tasks";
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl
new file mode 100644
index 000000000000..366193c2cc41
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.shared.system.smartspace;
+
+import com.android.systemui.shared.system.smartspace.SmartspaceState;
+
+// Methods for System UI to interface with Launcher to perform the unlock animation.
+interface ILauncherUnlockAnimationController {
+ // Prepares Launcher for the unlock animation by setting scale/alpha/etc. to their starting
+ // values.
+ void prepareForUnlock(boolean willAnimateSmartspace, int selectedPage);
+
+ // Set the unlock percentage. This is used when System UI is controlling each frame of the
+ // unlock animation, such as during a swipe to unlock touch gesture.
+ oneway void setUnlockAmount(float amount);
+
+ // Play a full unlock animation from 0f to 1f. This is used when System UI is unlocking from a
+ // single action, such as biometric auth, and doesn't need to control individual frames.
+ oneway void playUnlockAnimation(boolean unlocked, long duration);
+
+ // Set the selected page on Launcher's smartspace.
+ oneway void setSmartspaceSelectedPage(int selectedPage);
+
+ // Set the visibility of Launcher's smartspace.
+ void setSmartspaceVisibility(int visibility);
+
+ // Tell SystemUI the smartspace's current state. Launcher code should call this whenever the
+ // smartspace state may have changed.
+ oneway void dispatchSmartspaceStateToSysui();
+} \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceCallback.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceCallback.aidl
deleted file mode 100644
index 511df4c285b4..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceCallback.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2021 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.shared.system.smartspace;
-
-import com.android.systemui.shared.system.smartspace.SmartspaceState;
-
-// Methods for getting and setting the state of a SmartSpace. This is used to allow a remote process
-// (such as System UI) to sync with and control a SmartSpace view hosted in another process (such as
-// Launcher).
-interface ISmartspaceCallback {
-
- // Return information about the state of the SmartSpace, including location on-screen and
- // currently selected page.
- SmartspaceState getSmartspaceState();
-
- // Set the currently selected page of this SmartSpace.
- oneway void setSelectedPage(int selectedPage);
-
- oneway void setVisibility(int visibility);
-} \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceTransitionController.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceTransitionController.aidl
deleted file mode 100644
index 2b3e961ab3b2..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceTransitionController.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2021 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.shared.system.smartspace;
-
-import com.android.systemui.shared.system.smartspace.ISmartspaceCallback;
-
-// Controller that keeps track of SmartSpace instances in remote processes (such as Launcher).
-interface ISmartspaceTransitionController {
- oneway void setSmartspace(ISmartspaceCallback callback);
-} \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISysuiUnlockAnimationController.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISysuiUnlockAnimationController.aidl
new file mode 100644
index 000000000000..cf83f62af550
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISysuiUnlockAnimationController.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.shared.system.smartspace;
+
+import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
+import com.android.systemui.shared.system.smartspace.SmartspaceState;
+
+// System UI unlock controller. Launcher will provide a LauncherUnlockAnimationController to this
+// controller, which System UI will use to control the unlock animation within the Launcher window.
+interface ISysuiUnlockAnimationController {
+ // Provides an implementation of the LauncherUnlockAnimationController to System UI, so that
+ // SysUI can use it to control the unlock animation in the launcher window.
+ oneway void setLauncherUnlockController(ILauncherUnlockAnimationController callback);
+
+ // Called by Launcher whenever anything happens to change the state of its smartspace. System UI
+ // proactively saves this and uses it to perform the unlock animation without needing to make a
+ // blocking query to Launcher asking about the smartspace state.
+ oneway void onLauncherSmartspaceStateUpdated(in SmartspaceState state);
+} \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
index 2d51c4d13611..d7e61d60aa55 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
@@ -28,15 +28,18 @@ import android.os.Parcelable
class SmartspaceState() : Parcelable {
var boundsOnScreen: Rect = Rect()
var selectedPage = 0
+ var visibleOnScreen = false
constructor(parcel: Parcel) : this() {
this.boundsOnScreen = parcel.readParcelable(Rect::javaClass.javaClass.classLoader)
this.selectedPage = parcel.readInt()
+ this.visibleOnScreen = parcel.readBoolean()
}
override fun writeToParcel(dest: Parcel?, flags: Int) {
dest?.writeParcelable(boundsOnScreen, 0)
dest?.writeInt(selectedPage)
+ dest?.writeBoolean(visibleOnScreen)
}
override fun describeContents(): Int {
@@ -44,7 +47,9 @@ class SmartspaceState() : Parcelable {
}
override fun toString(): String {
- return "boundsOnScreen: $boundsOnScreen, selectedPage: $selectedPage"
+ return "boundsOnScreen: $boundsOnScreen, " +
+ "selectedPage: $selectedPage, " +
+ "visibleOnScreen: $visibleOnScreen"
}
companion object CREATOR : Parcelable.Creator<SmartspaceState> {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 25b551139b44..8eb528980a96 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -20,6 +20,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
+import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import android.app.WallpaperManager;
import android.content.res.Resources;
@@ -41,7 +42,6 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -86,6 +86,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
private AnimatableClockController mLargeClockViewController;
private FrameLayout mLargeClockFrame; // centered clock
+ @KeyguardClockSwitch.ClockSize
+ private int mCurrentClockSize = SMALL;
+
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final KeyguardBypassController mBypassController;
@@ -110,7 +113,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
private View mSmartspaceView;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
- private SmartspaceTransitionController mSmartspaceTransitionController;
private boolean mOnlyClock = false;
private Executor mUiExecutor;
@@ -136,7 +138,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
KeyguardBypassController bypassController,
LockscreenSmartspaceController smartspaceController,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
- SmartspaceTransitionController smartspaceTransitionController,
SecureSettings secureSettings,
@Main Executor uiExecutor,
@Main Resources resources) {
@@ -155,7 +156,22 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
mSecureSettings = secureSettings;
mUiExecutor = uiExecutor;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
- mSmartspaceTransitionController = smartspaceTransitionController;
+ mKeyguardUnlockAnimationController.addKeyguardUnlockAnimationListener(
+ new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() {
+ @Override
+ public void onSmartspaceSharedElementTransitionStarted() {
+ // The smartspace needs to be able to translate out of bounds in order to
+ // end up where the launcher's smartspace is, while its container is being
+ // swiped off the top of the screen.
+ setClipChildrenForUnlock(false);
+ }
+
+ @Override
+ public void onUnlockAnimationFinished() {
+ // For performance reasons, reset this once the unlock animation ends.
+ setClipChildrenForUnlock(true);
+ }
+ });
}
/**
@@ -236,7 +252,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
mSmartspaceView.setPaddingRelative(startPadding, 0, endPadding, 0);
updateClockLayout();
- mSmartspaceTransitionController.setLockscreenSmartspace(mSmartspaceView);
+ mKeyguardUnlockAnimationController.setLockscreenSmartspace(mSmartspaceView);
}
mSecureSettings.registerContentObserver(
@@ -293,6 +309,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
return;
}
+ mCurrentClockSize = clockSize;
+
boolean appeared = mView.switchToClock(clockSize, animate);
if (animate && appeared && clockSize == LARGE) {
mLargeClockViewController.animateAppear();
@@ -368,7 +386,14 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
final Set<View> excludedViews = new HashSet<>();
if (mSmartspaceView != null) {
- excludedViews.add(mSmartspaceView);
+ excludedViews.add(mStatusArea);
+ }
+
+ // Don't change the alpha of the invisible clock.
+ if (mCurrentClockSize == LARGE) {
+ excludedViews.add(mClockFrame);
+ } else {
+ excludedViews.add(mLargeClockFrame);
}
setChildrenAlphaExcluding(alpha, excludedViews);
@@ -449,4 +474,16 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
mUiExecutor.execute(() -> displayClock(KeyguardClockSwitch.SMALL, /* animate */ true));
}
}
+
+ /**
+ * Sets the clipChildren property on relevant views, to allow the smartspace to draw out of
+ * bounds during the unlock transition.
+ */
+ private void setClipChildrenForUnlock(boolean clip) {
+ mView.setClipChildren(clip);
+
+ if (mStatusArea != null) {
+ mStatusArea.setClipChildren(clip);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 8bf890d7df50..a5fe0efc8887 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -22,7 +22,6 @@ import android.util.Slog;
import com.android.keyguard.KeyguardClockSwitch.ClockSize;
import com.android.systemui.communal.CommunalStateController;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
@@ -55,7 +54,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final KeyguardStateController mKeyguardStateController;
- private SmartspaceTransitionController mSmartspaceTransitionController;
private final Rect mClipBounds = new Rect();
@Inject
@@ -69,7 +67,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
ConfigurationController configurationController,
DozeParameters dozeParameters,
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
- SmartspaceTransitionController smartspaceTransitionController,
ScreenOffAnimationController screenOffAnimationController) {
super(keyguardStatusView);
mKeyguardSliceViewController = keyguardSliceViewController;
@@ -82,7 +79,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
keyguardStateController, dozeParameters, screenOffAnimationController,
/* animateYPos= */ true, /* visibleOnCommunal= */ false);
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
- mSmartspaceTransitionController = smartspaceTransitionController;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 9bc3f176e91a..b96c5aee4673 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -48,7 +48,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.Recents;
import com.android.systemui.screenshot.dagger.ScreenshotModule;
import com.android.systemui.settings.dagger.SettingsModule;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -188,12 +187,6 @@ public abstract class SystemUIModule {
return SystemUIFactory.getInstance();
}
- @SysUISingleton
- @Provides
- static SmartspaceTransitionController provideSmartspaceTransitionController() {
- return new SmartspaceTransitionController();
- }
-
// TODO: This should provided by the WM component
/** Provides Optional of BubbleManager */
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 4be819a49772..e24df30bfe34 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -85,7 +85,7 @@ public class Flags {
new BooleanFlag(400, true);
public static final BooleanFlag SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED =
- new BooleanFlag(401, false);
+ new BooleanFlag(401, true);
public static final ResourceBooleanFlag SMARTSPACE =
new ResourceBooleanFlag(402, R.bool.flag_smartspace);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 69bcf2ec8b8d..582965a12528 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -21,6 +21,8 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Matrix
+import android.graphics.Rect
+import android.os.Handler
import android.view.RemoteAnimationTarget
import android.view.SyncRtSurfaceTransactionApplier
import android.view.View
@@ -33,11 +35,17 @@ import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController
+import com.android.systemui.plugins.BcSmartspaceDataPlugin
+import com.android.systemui.shared.system.ActivityManagerWrapper
+import com.android.systemui.shared.system.QuickStepContract
+import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController
+import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController
+import com.android.systemui.shared.system.smartspace.SmartspaceState
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Lazy
import javax.inject.Inject
+import kotlin.math.min
/**
* Starting scale factor for the app/launcher surface behind the keyguard, when it's animating
@@ -76,6 +84,25 @@ const val DISMISS_AMOUNT_SHOW_SURFACE_THRESHOLD = 0.25f
const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.4f
/**
+ * How long the canned unlock animation takes. This is used if we are unlocking from biometric auth,
+ * from a tap on the unlock icon, or from the bouncer. This is not relevant if the lockscreen is
+ * swiped away via a touch gesture, or when it's flinging expanded/collapsed after a swipe.
+ */
+const val UNLOCK_ANIMATION_DURATION_MS = 200L
+
+/**
+ * Duration for the alpha animation on the surface behind. This plays to fade in the surface during
+ * a swipe to unlock (and to fade it back out if the swipe is cancelled).
+ */
+const val SURFACE_BEHIND_SWIPE_FADE_DURATION_MS = 150L
+
+/**
+ * Start delay for the surface behind animation, used so that the lockscreen can get out of the way
+ * before the surface begins appearing.
+ */
+const val UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L
+
+/**
* Initiates, controls, and ends the keyguard unlock animation.
*
* The unlock animation transitions between the keyguard (lock screen) and the app/launcher surface
@@ -85,7 +112,7 @@ const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.4f
* this controller will play a canned animation on the surface as well.
*
* The surface behind the keyguard is manipulated via a RemoteAnimation passed to
- * [notifyStartKeyguardExitAnimation] by [KeyguardViewMediator].
+ * [notifyStartSurfaceBehindRemoteAnimation] by [KeyguardViewMediator].
*/
@SysUISingleton
class KeyguardUnlockAnimationController @Inject constructor(
@@ -94,10 +121,99 @@ class KeyguardUnlockAnimationController @Inject constructor(
private val
keyguardViewMediator: Lazy<KeyguardViewMediator>,
private val keyguardViewController: KeyguardViewController,
- private val smartspaceTransitionController: SmartspaceTransitionController,
private val featureFlags: FeatureFlags,
- private val biometricUnlockController: BiometricUnlockController
-) : KeyguardStateController.Callback {
+ private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>
+) : KeyguardStateController.Callback, ISysuiUnlockAnimationController.Stub() {
+
+ interface KeyguardUnlockAnimationListener {
+ /**
+ * Called when the remote unlock animation, controlled by
+ * [KeyguardUnlockAnimationController], first starts.
+ *
+ * [playingCannedAnimation] indicates whether we are playing a canned animation to show the
+ * app/launcher behind the keyguard, vs. this being a swipe to unlock where the dismiss
+ * amount drives the animation.
+ * [fromWakeAndUnlock] tells us whether we are unlocking directly from AOD - in this case,
+ * the lockscreen is dismissed instantly, so we shouldn't run any animations that rely on it
+ * being visible.
+ */
+ @JvmDefault
+ fun onUnlockAnimationStarted(playingCannedAnimation: Boolean, fromWakeAndUnlock: Boolean) {}
+
+ /**
+ * Called when the remote unlock animation ends, in all cases, canned or swipe-to-unlock.
+ * The keyguard is no longer visible in this state and the app/launcher behind the keyguard
+ * is now completely visible.
+ */
+ @JvmDefault
+ fun onUnlockAnimationFinished() {}
+
+ /**
+ * Called when we begin the smartspace shared element transition, either due to an unlock
+ * action (biometric, etc.) or a swipe to unlock.
+ *
+ * This transition can begin BEFORE [onUnlockAnimationStarted] is called, if we are swiping
+ * to unlock and the surface behind the keyguard has not yet been made visible. This is
+ * because the lockscreen smartspace immediately begins moving towards the launcher
+ * smartspace location when a swipe begins, even before we start the keyguard exit remote
+ * animation and show the launcher itself.
+ */
+ @JvmDefault
+ fun onSmartspaceSharedElementTransitionStarted() {}
+ }
+
+ /** The SmartSpace view on the lockscreen, provided by [KeyguardClockSwitchController]. */
+ var lockscreenSmartspace: View? = null
+
+ /**
+ * The state of the Launcher's smartspace, delivered via [onLauncherSmartspaceStateUpdated].
+ * This is pushed to us from Launcher whenever their smartspace moves or its visibility changes.
+ * We'll animate the lockscreen smartspace to this location during an unlock.
+ */
+ var launcherSmartspaceState: SmartspaceState? = null
+
+ /**
+ * Whether a canned unlock animation is playing, vs. currently unlocking in response to a swipe
+ * gesture or panel fling. If we're swiping/flinging, the unlock animation is driven by the
+ * dismiss amount, via [onKeyguardDismissAmountChanged]. If we're using a canned animation, it's
+ * being driven by ValueAnimators started in [playCannedUnlockAnimation].
+ */
+ var playingCannedUnlockAnimation = false
+
+ /**
+ * Remote callback provided by Launcher that allows us to control the Launcher's unlock
+ * animation and smartspace.
+ *
+ * If this is null, we will not be animating any Launchers today and should fall back to window
+ * animations.
+ */
+ private var launcherUnlockController: ILauncherUnlockAnimationController? = null
+
+ private val listeners = ArrayList<KeyguardUnlockAnimationListener>()
+
+ /**
+ * Called from SystemUiProxy to pass us the launcher's unlock animation controller. If this
+ * doesn't happen, we won't use in-window animations or the smartspace shared element
+ * transition, but that's okay!
+ */
+ override fun setLauncherUnlockController(callback: ILauncherUnlockAnimationController?) {
+ launcherUnlockController = callback
+
+ // If the provided callback dies, set it to null. We'll always check whether it's null
+ // to avoid DeadObjectExceptions.
+ callback?.asBinder()?.linkToDeath({
+ launcherUnlockController = null
+ launcherSmartspaceState = null
+ }, 0 /* flags */)
+ }
+
+ /**
+ * Called from SystemUiProxy to pass us the latest state of the Launcher's smartspace. This is
+ * only done when the state has changed in some way.
+ */
+ override fun onLauncherSmartspaceStateUpdated(state: SmartspaceState?) {
+ launcherSmartspaceState = state
+ }
/**
* Information used to start, run, and finish a RemoteAnimation on the app or launcher surface
@@ -105,15 +221,16 @@ class KeyguardUnlockAnimationController @Inject constructor(
*
* If we're swiping to unlock, the "animation" is controlled via the gesture, tied to the
* dismiss amounts received in [onKeyguardDismissAmountChanged]. It does not have a fixed
- * duration, and it ends when the gesture reaches a certain threshold or is cancelled.
+ * duration, and it ends when the gesture reaches a certain threshold or is cancell
*
* If we're unlocking via biometrics, PIN entry, or from clicking a notification, a canned
- * animation is started in [notifyStartKeyguardExitAnimation].
+ * animation is started in [playCannedUnlockAnimation].
*/
@VisibleForTesting
var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null
private var surfaceBehindRemoteAnimationTarget: RemoteAnimationTarget? = null
private var surfaceBehindRemoteAnimationStartTime: Long = 0
+ private var surfaceBehindParams: SyncRtSurfaceTransactionApplier.SurfaceParams? = null
/**
* Alpha value applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the
@@ -125,6 +242,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
*/
private var surfaceBehindAlpha = 1f
private var surfaceBehindAlphaAnimator = ValueAnimator.ofFloat(0f, 1f)
+ private var smartspaceAnimator = ValueAnimator.ofFloat(0f, 1f)
/**
* Matrix applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the
@@ -144,57 +262,113 @@ class KeyguardUnlockAnimationController @Inject constructor(
/** Rounded corner radius to apply to the surface behind the keyguard. */
private var roundedCornerRadius = 0f
- /** The SmartSpace view on the lockscreen, provided by [KeyguardClockSwitchController]. */
- public var lockscreenSmartSpace: View? = null
+ /**
+ * Whether we tried to start the SmartSpace shared element transition for this unlock swipe.
+ * It's possible we were unable to do so (if the Launcher SmartSpace is not available), and we
+ * need to keep track of that so that we don't start doing it halfway through the swipe if
+ * Launcher becomes available suddenly.
+ */
+ private var attemptedSmartSpaceTransitionForThisSwipe = false
/**
- * Whether we are currently in the process of unlocking the keyguard, and we are performing the
- * shared element SmartSpace transition.
+ * The original location of the lockscreen smartspace on the screen.
*/
- private var unlockingWithSmartSpaceTransition: Boolean = false
+ private val smartspaceOriginBounds = Rect()
/**
- * Whether we tried to start the SmartSpace shared element transition for this unlock swipe.
- * It's possible we're unable to do so (if the Launcher SmartSpace is not available).
+ * The bounds to which the lockscreen smartspace is moving. This is set to the bounds of the
+ * launcher's smartspace prior to the transition starting.
*/
- private var attemptedSmartSpaceTransitionForThisSwipe = false
+ private val smartspaceDestBounds = Rect()
+
+ /**
+ * From 0f to 1f, the progress of the smartspace shared element animation. 0f means the
+ * smartspace is at its normal position within the lock screen hierarchy, and 1f means it has
+ * fully animated to the location of the Launcher's smartspace.
+ */
+ private var smartspaceUnlockProgress = 0f
+
+ /**
+ * Whether we're currently unlocking, and we're talking to Launcher to perform in-window
+ * animations rather than simply animating the Launcher window like any other app. This can be
+ * true while [unlockingWithSmartspaceTransition] is false, if the smartspace is not available
+ * or was not ready in time.
+ */
+ private var unlockingToLauncherWithInWindowAnimations: Boolean = false
+
+ /**
+ * Whether we are currently unlocking, and the smartspace shared element transition is in
+ * progress. If true, we're also [unlockingToLauncherWithInWindowAnimations].
+ */
+ private var unlockingWithSmartspaceTransition: Boolean = false
+
+ private val handler = Handler()
init {
- surfaceBehindAlphaAnimator.duration = 150
- surfaceBehindAlphaAnimator.interpolator = Interpolators.ALPHA_IN
- surfaceBehindAlphaAnimator.addUpdateListener { valueAnimator: ValueAnimator ->
- surfaceBehindAlpha = valueAnimator.animatedValue as Float
- updateSurfaceBehindAppearAmount()
- }
- surfaceBehindAlphaAnimator.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator) {
- // If the surface alpha is 0f, it's no longer visible so we can safely be done with
- // the animation.
- if (surfaceBehindAlpha == 0f) {
- keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation(
+ with(surfaceBehindAlphaAnimator) {
+ duration = SURFACE_BEHIND_SWIPE_FADE_DURATION_MS
+ interpolator = Interpolators.TOUCH_RESPONSE
+ addUpdateListener { valueAnimator: ValueAnimator ->
+ surfaceBehindAlpha = valueAnimator.animatedValue as Float
+ updateSurfaceBehindAppearAmount()
+ }
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ // If the surface alpha is 0f, it's no longer visible so we can safely be done
+ // with the animation even if other properties are still animating.
+ if (surfaceBehindAlpha == 0f) {
+ keyguardViewMediator.get().finishSurfaceBehindRemoteAnimation(
false /* cancelled */)
+ }
}
- }
- })
+ })
+ }
- surfaceBehindEntryAnimator.duration = 450
- surfaceBehindEntryAnimator.interpolator = Interpolators.DECELERATE_QUINT
- surfaceBehindEntryAnimator.addUpdateListener { valueAnimator: ValueAnimator ->
- surfaceBehindAlpha = valueAnimator.animatedValue as Float
- setSurfaceBehindAppearAmount(valueAnimator.animatedValue as Float)
+ with(surfaceBehindEntryAnimator) {
+ duration = UNLOCK_ANIMATION_DURATION_MS
+ startDelay = UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS
+ interpolator = Interpolators.TOUCH_RESPONSE
+ addUpdateListener { valueAnimator: ValueAnimator ->
+ surfaceBehindAlpha = valueAnimator.animatedValue as Float
+ setSurfaceBehindAppearAmount(valueAnimator.animatedValue as Float)
+ }
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ playingCannedUnlockAnimation = false
+ keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ false /* cancelled */
+ )
+ }
+ })
}
- surfaceBehindEntryAnimator.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator) {
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
- false /* cancelled */)
+
+ with(smartspaceAnimator) {
+ duration = UNLOCK_ANIMATION_DURATION_MS
+ interpolator = Interpolators.TOUCH_RESPONSE
+ addUpdateListener {
+ smartspaceUnlockProgress = it.animatedValue as Float
}
- })
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ launcherUnlockController?.setSmartspaceVisibility(View.VISIBLE)
+ keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ false /* cancelled */)
+ }
+ })
+ }
// Listen for changes in the dismiss amount.
keyguardStateController.addCallback(this)
roundedCornerRadius =
- context.resources.getDimensionPixelSize(R.dimen.rounded_corner_radius).toFloat()
+ context.resources.getDimensionPixelSize(R.dimen.rounded_corner_radius).toFloat()
+ }
+
+ /**
+ * Add a listener to be notified of various stages of the unlock animation.
+ */
+ fun addKeyguardUnlockAnimationListener(listener: KeyguardUnlockAnimationListener) {
+ listeners.add(listener)
}
/**
@@ -203,78 +377,220 @@ class KeyguardUnlockAnimationController @Inject constructor(
* surface for the unlock gesture/animation.
*
* When we're done with it, we'll call [KeyguardViewMediator.finishSurfaceBehindRemoteAnimation]
- * to end the RemoteAnimation.
+ * to end the RemoteAnimation. The KeyguardViewMediator will then end the animation and let us
+ * know that it's over by calling [notifyFinishedKeyguardExitAnimation].
*
- * [requestedShowSurfaceBehindKeyguard] denotes whether the exit animation started because of a
+ * [requestedShowSurfaceBehindKeyguard] indicates whether the animation started because of a
* call to [KeyguardViewMediator.showSurfaceBehindKeyguard], as happens during a swipe gesture,
- * as opposed to the keyguard hiding.
+ * as opposed to being called because the device was unlocked and the keyguard is going away.
*/
- fun notifyStartKeyguardExitAnimation(
+ fun notifyStartSurfaceBehindRemoteAnimation(
target: RemoteAnimationTarget,
startTime: Long,
requestedShowSurfaceBehindKeyguard: Boolean
) {
-
if (surfaceTransactionApplier == null) {
surfaceTransactionApplier = SyncRtSurfaceTransactionApplier(
keyguardViewController.viewRootImpl.view)
}
+ // New animation, new params.
+ surfaceBehindParams = null
+
surfaceBehindRemoteAnimationTarget = target
surfaceBehindRemoteAnimationStartTime = startTime
- // If the surface behind wasn't made visible during a swipe, we'll do a canned animation
- // to animate it in. Otherwise, the swipe touch events will continue animating it.
+ // If we specifically requested that the surface behind be made visible, it means we are
+ // swiping to unlock. In that case, the surface visibility is tied to the dismiss amount,
+ // and we'll handle that in onKeyguardDismissAmountChanged(). If we didn't request that, the
+ // keyguard is being dismissed for a different reason (biometric auth, etc.) and we should
+ // play a canned animation to make the surface fully visible.
if (!requestedShowSurfaceBehindKeyguard) {
- keyguardViewController.hide(startTime, 350)
-
- // If we're wake and unlocking, we don't want to animate the surface since we're going
- // to do the light reveal scrim from the black AOD screen. Make it visible and end the
- // remote aimation.
- if (biometricUnlockController.isWakeAndUnlock) {
- setSurfaceBehindAppearAmount(1f)
- keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
- false /* cancelled */)
- } else {
- // Otherwise, animate it in normally.
- surfaceBehindEntryAnimator.start()
- }
+ playCannedUnlockAnimation()
}
+ listeners.forEach {
+ it.onUnlockAnimationStarted(
+ playingCannedUnlockAnimation /* playingCannedAnimation */,
+ biometricUnlockControllerLazy.get().isWakeAndUnlock /* isWakeAndUnlock */) }
+
// Finish the keyguard remote animation if the dismiss amount has crossed the threshold.
// Check it here in case there is no more change to the dismiss amount after the last change
// that starts the keyguard animation. @see #updateKeyguardViewMediatorIfThresholdsReached()
finishKeyguardExitRemoteAnimationIfReachThreshold()
}
- fun notifyCancelKeyguardExitAnimation() {
+ /**
+ * Called by [KeyguardViewMediator] to let us know that the remote animation has finished, and
+ * we should clean up all of our state.
+ */
+ fun notifyFinishedKeyguardExitAnimation(cancelled: Boolean) {
+ // Cancel any pending actions.
+ handler.removeCallbacksAndMessages(null)
+
+ // Make sure we made the surface behind fully visible, just in case. It should already be
+ // fully visible.
+ setSurfaceBehindAppearAmount(1f)
+ launcherUnlockController?.setUnlockAmount(1f)
+ smartspaceDestBounds.setEmpty()
+
+ // That target is no longer valid since the animation finished, null it out.
surfaceBehindRemoteAnimationTarget = null
+ surfaceBehindParams = null
+
+ playingCannedUnlockAnimation = false
+ unlockingToLauncherWithInWindowAnimations = false
+ unlockingWithSmartspaceTransition = false
+ resetSmartspaceTransition()
+
+ listeners.forEach { it.onUnlockAnimationFinished() }
}
- fun notifyFinishedKeyguardExitAnimation() {
- surfaceBehindRemoteAnimationTarget = null
+ /**
+ * Play a canned unlock animation to unlock the device. This is used when we were *not* swiping
+ * to unlock using a touch gesture. If we were swiping to unlock, the animation will be driven
+ * by the dismiss amount via [onKeyguardDismissAmountChanged].
+ */
+ fun playCannedUnlockAnimation() {
+ playingCannedUnlockAnimation = true
+
+ if (canPerformInWindowLauncherAnimations()) {
+ // If possible, use the neat in-window animations to unlock to the launcher.
+ unlockToLauncherWithInWindowAnimations()
+ } else if (!biometricUnlockControllerLazy.get().isWakeAndUnlock) {
+ // If the launcher isn't behind the keyguard, or the launcher unlock controller is not
+ // available, animate in the entire window.
+ surfaceBehindEntryAnimator.start()
+ } else {
+ setSurfaceBehindAppearAmount(1f)
+ keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(false)
+ }
+
+ // If this is a wake and unlock, hide the lockscreen immediately. In the future, we should
+ // animate it out nicely instead, but to the current state of wake and unlock, not hiding it
+ // causes a lot of issues.
+ // TODO(b/210016643): Not this, it looks not-ideal!
+ if (biometricUnlockControllerLazy.get().isWakeAndUnlock) {
+ keyguardViewController.hide(surfaceBehindRemoteAnimationStartTime, 350)
+ }
}
- fun hideKeyguardViewAfterRemoteAnimation() {
- keyguardViewController.hide(surfaceBehindRemoteAnimationStartTime, 350)
+ /**
+ * Unlock to the launcher, using in-window animations, and the smartspace shared element
+ * transition if possible.
+ */
+ private fun unlockToLauncherWithInWindowAnimations() {
+ unlockingToLauncherWithInWindowAnimations = true
+
+ // See if we can do the smartspace transition, and if so, do it!
+ if (prepareForSmartspaceTransition()) {
+ animateSmartspaceToDestination()
+ listeners.forEach { it.onSmartspaceSharedElementTransitionStarted() }
+ }
+
+ // Tell the launcher to prepare for the animation by setting its views invisible and
+ // syncing the selected smartspace pages.
+ launcherUnlockController?.prepareForUnlock(
+ unlockingWithSmartspaceTransition /* willAnimateSmartspace */,
+ (lockscreenSmartspace as BcSmartspaceDataPlugin.SmartspaceView?)?.selectedPage ?: -1)
+
+ // Begin the animation.
+ launcherUnlockController?.playUnlockAnimation(
+ true /* unlocked */, UNLOCK_ANIMATION_DURATION_MS)
+ if (!unlockingWithSmartspaceTransition) {
+ // If we are not unlocking with the smartspace transition, wait for the unlock animation
+ // to end and then finish the remote animation. If we are using the smartspace
+ // transition, it will finish the remote animation once it ends.
+ handler.postDelayed({
+ keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
+ false /* cancelled */)
+ }, UNLOCK_ANIMATION_DURATION_MS)
+ }
+
+ // Wait a moment, then show the launcher surface.
+ setSurfaceBehindAppearAmount(1f)
}
/**
- * Whether we are currently in the process of unlocking the keyguard, and we are performing the
- * shared element SmartSpace transition.
+ * Animates the lockscreen smartspace all the way to the launcher's smartspace location, then
+ * makes the launcher smartspace visible and ends the remote animation.
*/
- fun isUnlockingWithSmartSpaceTransition(): Boolean {
- return unlockingWithSmartSpaceTransition
+ private fun animateSmartspaceToDestination() {
+ smartspaceAnimator.start()
+ }
+
+ /**
+ * Reset the lockscreen smartspace's position, and reset all state involving the smartspace
+ * transition.
+ */
+ public fun resetSmartspaceTransition() {
+ unlockingWithSmartspaceTransition = false
+ smartspaceUnlockProgress = 0f
+
+ lockscreenSmartspace?.post {
+ lockscreenSmartspace!!.translationX = 0f
+ lockscreenSmartspace!!.translationY = 0f
+ }
+ }
+
+ /**
+ * Moves the lockscreen smartspace towards the launcher smartspace's position.
+ */
+ private fun setSmartspaceProgressToDestinationBounds(progress: Float) {
+ if (smartspaceDestBounds.isEmpty) {
+ return
+ }
+
+ val progressClamped = min(1f, progress)
+
+ // Calculate the distance (relative to the origin) that we need to be for the current
+ // progress value.
+ val progressX =
+ (smartspaceDestBounds.left - smartspaceOriginBounds.left) * progressClamped
+ val progressY =
+ (smartspaceDestBounds.top - smartspaceOriginBounds.top) * progressClamped
+
+ val lockscreenSmartspaceCurrentBounds = Rect().also {
+ lockscreenSmartspace!!.getBoundsOnScreen(it)
+ }
+
+ // Figure out how far that is from our present location on the screen. This approach
+ // compensates for the fact that our parent container is also translating to animate out.
+ val dx = smartspaceOriginBounds.left + progressX -
+ lockscreenSmartspaceCurrentBounds.left
+ val dy = smartspaceOriginBounds.top + progressY -
+ lockscreenSmartspaceCurrentBounds.top
+
+ with(lockscreenSmartspace!!) {
+ translationX += dx
+ translationY += dy
+ }
}
/**
* Update the lockscreen SmartSpace to be positioned according to the current dismiss amount. As
* the dismiss amount increases, we will increase our SmartSpace's progress to the destination
* bounds (the location of the Launcher SmartSpace).
+ *
+ * This is used by [KeyguardClockSwitchController] to keep the smartspace position updated as
+ * the clock is swiped away.
*/
fun updateLockscreenSmartSpacePosition() {
- smartspaceTransitionController.setProgressToDestinationBounds(
- keyguardStateController.dismissAmount / DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)
+ setSmartspaceProgressToDestinationBounds(smartspaceUnlockProgress)
+ }
+
+ /**
+ * Asks the keyguard view to hide, using the start time from the beginning of the remote
+ * animation.
+ */
+ fun hideKeyguardViewAfterRemoteAnimation() {
+ // Hide the keyguard, with no fade out since we animated it away during the unlock.
+ keyguardViewController.hide(surfaceBehindRemoteAnimationStartTime, 0 /* fadeOutDuration */)
+ }
+
+ private fun applyParamsToSurface(params: SyncRtSurfaceTransactionApplier.SurfaceParams) {
+ surfaceTransactionApplier!!.scheduleApply(params)
+ surfaceBehindParams = params
}
/**
@@ -287,34 +603,56 @@ class KeyguardUnlockAnimationController @Inject constructor(
return
}
- val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.height()
- val scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR +
- (1f - SURFACE_BEHIND_START_SCALE_FACTOR) *
- MathUtils.clamp(amount, 0f, 1f))
+ if (unlockingToLauncherWithInWindowAnimations) {
+ // If we're using the in-window launcher animations, and haven't yet applied alpha = 1f
+ // to the launcher surface, do that now so we can see the launcher animations.
+ if (surfaceBehindParams?.alpha?.let { it < 1f } != false) {
+ applyParamsToSurface(
+ SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
+ surfaceBehindRemoteAnimationTarget!!.leash)
+ .withAlpha(1f)
+ .build())
+ }
- // Scale up from a point at the center-bottom of the surface.
- surfaceBehindMatrix.setScale(
+ // If we aren't using the canned unlock animation (which would be setting the unlock
+ // amount in its update listener), do it here.
+ if (!isPlayingCannedUnlockAnimation()) {
+ launcherUnlockController?.setUnlockAmount(amount)
+ }
+ } else {
+ // Otherwise, animate in the surface's scale/transltion.
+ val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.height()
+ val scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR +
+ (1f - SURFACE_BEHIND_START_SCALE_FACTOR) *
+ MathUtils.clamp(amount, 0f, 1f))
+
+ // Scale up from a point at the center-bottom of the surface.
+ surfaceBehindMatrix.setScale(
scaleFactor,
scaleFactor,
surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.width() / 2f,
- surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y)
+ surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y
+ )
- // Translate up from the bottom.
- surfaceBehindMatrix.postTranslate(0f,
- surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount))
+ // Translate up from the bottom.
+ surfaceBehindMatrix.postTranslate(
+ 0f,
+ surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount)
+ )
- // If we're snapping the keyguard back, immediately begin fading it out.
- val animationAlpha =
+ // If we're snapping the keyguard back, immediately begin fading it out.
+ val animationAlpha =
if (keyguardStateController.isSnappingKeyguardBackAfterSwipe) amount
else surfaceBehindAlpha
- val params = SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
- surfaceBehindRemoteAnimationTarget!!.leash)
+ applyParamsToSurface(
+ SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
+ surfaceBehindRemoteAnimationTarget!!.leash)
.withMatrix(surfaceBehindMatrix)
.withCornerRadius(roundedCornerRadius)
.withAlpha(animationAlpha)
- .build()
- surfaceTransactionApplier!!.scheduleApply(params)
+ .build())
+ }
}
/**
@@ -326,6 +664,10 @@ class KeyguardUnlockAnimationController @Inject constructor(
return
}
+ if (playingCannedUnlockAnimation) {
+ return
+ }
+
// For fling animations, we want to animate the surface in over the full distance. If we're
// dismissing the keyguard via a swipe gesture (or cancelling the swipe gesture), we want to
// bring in the surface behind over a relatively short swipe distance (~15%), to keep the
@@ -344,17 +686,19 @@ class KeyguardUnlockAnimationController @Inject constructor(
}
override fun onKeyguardDismissAmountChanged() {
- if (!KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation) {
+ if (!willHandleUnlockAnimation()) {
return
}
if (keyguardViewController.isShowing) {
- updateKeyguardViewMediatorIfThresholdsReached()
+ showOrHideSurfaceIfDismissAmountThresholdsReached()
// If the surface is visible or it's about to be, start updating its appearance to
// reflect the new dismiss amount.
- if (keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard() ||
- keyguardViewMediator.get().isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe) {
+ if ((keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard() ||
+ keyguardViewMediator.get()
+ .isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe) &&
+ !playingCannedUnlockAnimation) {
updateSurfaceBehindAppearAmount()
}
}
@@ -362,7 +706,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
// The end of the SmartSpace transition can occur after the keyguard is hidden (when we tell
// Launcher's SmartSpace to become visible again), so update it even if the keyguard view is
// no longer showing.
- updateSmartSpaceTransition()
+ applyDismissAmountToSmartspaceTransition()
}
/**
@@ -370,16 +714,28 @@ class KeyguardUnlockAnimationController @Inject constructor(
* such as reaching the point in the dismiss swipe where we need to make the surface behind the
* keyguard visible.
*/
- private fun updateKeyguardViewMediatorIfThresholdsReached() {
+ private fun showOrHideSurfaceIfDismissAmountThresholdsReached() {
if (!featureFlags.isEnabled(Flags.NEW_UNLOCK_SWIPE_ANIMATION)) {
return
}
+ // If we are playing the canned unlock animation, we flung away the keyguard to hide it and
+ // started a canned animation to show the surface behind the keyguard. The fling will cause
+ // panel height/dismiss amount updates, but we should ignore those updates here since the
+ // surface behind is already visible and animating.
+ if (playingCannedUnlockAnimation) {
+ return
+ }
+
val dismissAmount = keyguardStateController.dismissAmount
if (dismissAmount >= DISMISS_AMOUNT_SHOW_SURFACE_THRESHOLD &&
!keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard()) {
// We passed the threshold, and we're not yet showing the surface behind the
// keyguard. Animate it in.
+ if (canPerformInWindowLauncherAnimations()) {
+ launcherUnlockController?.setUnlockAmount(0f)
+ unlockingToLauncherWithInWindowAnimations = true
+ }
keyguardViewMediator.get().showSurfaceBehindKeyguard()
fadeInSurfaceBehind()
} else if (dismissAmount < DISMISS_AMOUNT_SHOW_SURFACE_THRESHOLD &&
@@ -388,9 +744,9 @@ class KeyguardUnlockAnimationController @Inject constructor(
// out.
keyguardViewMediator.get().hideSurfaceBehindKeyguard()
fadeOutSurfaceBehind()
- } else {
- finishKeyguardExitRemoteAnimationIfReachThreshold()
}
+
+ finishKeyguardExitRemoteAnimationIfReachThreshold()
}
/**
@@ -417,6 +773,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
// animating it out. This will be called again after the fling ends.
!keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture &&
dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) {
+ setSurfaceBehindAppearAmount(1f)
keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(false /* cancelled */)
}
}
@@ -426,31 +783,53 @@ class KeyguardUnlockAnimationController @Inject constructor(
* dismiss amount, and also updates the SmartSpaceTransitionController, which will let Launcher
* know if it needs to do something as a result.
*/
- private fun updateSmartSpaceTransition() {
+ private fun applyDismissAmountToSmartspaceTransition() {
if (!featureFlags.isEnabled(Flags.SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED)) {
return
}
+ // If we are playing the canned animation, the smartspace is being animated directly between
+ // its original location and the location of the launcher smartspace by smartspaceAnimator.
+ // We can ignore the dismiss amount, which is caused by panel height changes as the panel is
+ // flung away.
+ if (playingCannedUnlockAnimation) {
+ return
+ }
+
val dismissAmount = keyguardStateController.dismissAmount
- // If we've begun a swipe, and are capable of doing the SmartSpace transition, start it!
+ // If we've begun a swipe, and haven't yet tried doing the SmartSpace transition, do that
+ // now.
if (!attemptedSmartSpaceTransitionForThisSwipe &&
- dismissAmount > 0f &&
- dismissAmount < 1f &&
- keyguardViewController.isShowing) {
+ keyguardViewController.isShowing &&
+ dismissAmount > 0f &&
+ dismissAmount < 1f) {
attemptedSmartSpaceTransitionForThisSwipe = true
- smartspaceTransitionController.prepareForUnlockTransition()
- if (keyguardStateController.canPerformSmartSpaceTransition()) {
- unlockingWithSmartSpaceTransition = true
- smartspaceTransitionController.launcherSmartspace?.setVisibility(
- View.INVISIBLE)
+ if (prepareForSmartspaceTransition()) {
+ unlockingWithSmartspaceTransition = true
+
+ // Ensure that the smartspace is invisible if we're doing the transition, and
+ // visible if we aren't.
+ launcherUnlockController?.setSmartspaceVisibility(
+ if (unlockingWithSmartspaceTransition) View.INVISIBLE else View.VISIBLE)
+
+ if (unlockingWithSmartspaceTransition) {
+ listeners.forEach { it.onSmartspaceSharedElementTransitionStarted() }
+ }
}
} else if (attemptedSmartSpaceTransitionForThisSwipe &&
- (dismissAmount == 0f || dismissAmount == 1f)) {
+ (dismissAmount == 0f || dismissAmount == 1f)) {
attemptedSmartSpaceTransitionForThisSwipe = false
- unlockingWithSmartSpaceTransition = false
- smartspaceTransitionController.launcherSmartspace?.setVisibility(View.VISIBLE)
+ unlockingWithSmartspaceTransition = false
+ launcherUnlockController?.setSmartspaceVisibility(View.VISIBLE)
+ }
+
+ if (unlockingWithSmartspaceTransition) {
+ val swipedFraction: Float = keyguardStateController.dismissAmount
+ val progress = swipedFraction / DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD
+ smartspaceUnlockProgress = progress
+ setSmartspaceProgressToDestinationBounds(smartspaceUnlockProgress)
}
}
@@ -463,4 +842,121 @@ class KeyguardUnlockAnimationController @Inject constructor(
surfaceBehindAlphaAnimator.cancel()
surfaceBehindAlphaAnimator.reverse()
}
+
+ /**
+ * Prepare for the smartspace shared element transition, if possible, by figuring out where we
+ * are animating from/to.
+ *
+ * Return true if we'll be able to do the smartspace transition, or false if conditions are not
+ * right to do it right now.
+ */
+ private fun prepareForSmartspaceTransition(): Boolean {
+ // Feature is disabled, so we don't want to.
+ if (!featureFlags.isEnabled(Flags.SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED)) {
+ return false
+ }
+
+ // If our controllers are null, or we haven't received a smartspace state from Launcher yet,
+ // we will not be doing any smartspace transitions today.
+ if (launcherUnlockController == null ||
+ lockscreenSmartspace == null ||
+ launcherSmartspaceState == null) {
+ return false
+ }
+
+ // If the launcher does not have a visible smartspace (either because it's paged off-screen,
+ // or the smartspace just doesn't exist), we can't do the transition.
+ if ((launcherSmartspaceState?.visibleOnScreen) != true) {
+ return false
+ }
+
+ // If our launcher isn't underneath, then we're unlocking to an app or custom launcher,
+ // neither of which have a smartspace.
+ if (!isNexusLauncherUnderneath()) {
+ return false
+ }
+
+ // TODO(b/213910911): Unfortunately the keyguard is hidden instantly on wake and unlock, so
+ // we won't have a lockscreen smartspace to animate. This is sad, and we should fix that!
+ if (biometricUnlockControllerLazy.get().isWakeAndUnlock) {
+ return false
+ }
+
+ // If we can't dismiss the lock screen via a swipe, then the only way we can do the shared
+ // element transition is if we're doing a biometric unlock. Otherwise, it means the bouncer
+ // is showing, and you can't see the lockscreen smartspace, so a shared element transition
+ // would not make sense.
+ if (!keyguardStateController.canDismissLockScreen() &&
+ !biometricUnlockControllerLazy.get().isBiometricUnlock) {
+ return false
+ }
+
+ unlockingWithSmartspaceTransition = true
+ smartspaceDestBounds.setEmpty()
+
+ // Assuming we were able to retrieve the launcher's state, start the lockscreen
+ // smartspace at 0, 0, and save its starting bounds.
+ with(lockscreenSmartspace!!) {
+ translationX = 0f
+ translationY = 0f
+ getBoundsOnScreen(smartspaceOriginBounds)
+ }
+
+ // Set the destination bounds to the launcher smartspace's bounds, offset by any
+ // padding on our smartspace.
+ with(smartspaceDestBounds) {
+ set(launcherSmartspaceState!!.boundsOnScreen)
+ offset(-lockscreenSmartspace!!.paddingLeft, -lockscreenSmartspace!!.paddingTop)
+ }
+
+ return true
+ }
+
+ /**
+ * Whether we should be able to do the in-window launcher animations given the current state of
+ * the device.
+ */
+ fun canPerformInWindowLauncherAnimations(): Boolean {
+ return isNexusLauncherUnderneath() && launcherUnlockController != null
+ }
+
+ /**
+ * Whether we are currently in the process of unlocking the keyguard, and we are performing the
+ * shared element SmartSpace transition.
+ */
+ fun isUnlockingWithSmartSpaceTransition(): Boolean {
+ return unlockingWithSmartspaceTransition
+ }
+
+ /**
+ * Whether this animation controller will be handling the unlock. We require remote animations
+ * to be enabled to do this.
+ *
+ * If this is not true, nothing in this class is relevant, and the unlock will be handled in
+ * [KeyguardViewMediator].
+ */
+ fun willHandleUnlockAnimation(): Boolean {
+ return KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation
+ }
+
+ /**
+ * Whether we are playing a canned unlock animation, vs. unlocking from a touch gesture such as
+ * a swipe.
+ */
+ fun isPlayingCannedUnlockAnimation(): Boolean {
+ return playingCannedUnlockAnimation
+ }
+
+ companion object {
+ /**
+ * Return whether the Google Nexus launcher is underneath the keyguard, vs. some other
+ * launcher or an app. If so, we can communicate with it to perform in-window/shared element
+ * transitions!
+ */
+ fun isNexusLauncherUnderneath(): Boolean {
+ return ActivityManagerWrapper.getInstance()
+ .runningTask?.topActivity?.className?.equals(
+ QuickStepContract.LAUNCHER_ACTIVITY_CLASS_NAME) ?: false
+ }
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8376681e7bd4..08e1654c8dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2235,8 +2235,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
createInteractionJankMonitorConf("DismissPanel"));
// Pass the surface and metadata to the unlock animation controller.
- mKeyguardUnlockAnimationControllerLazy.get().notifyStartKeyguardExitAnimation(
- apps[0], startTime, mSurfaceBehindRemoteAnimationRequested);
+ mKeyguardUnlockAnimationControllerLazy.get()
+ .notifyStartSurfaceBehindRemoteAnimation(
+ apps[0], startTime, mSurfaceBehindRemoteAnimationRequested);
} else {
mInteractionJankMonitor.begin(
createInteractionJankMonitorConf("RemoteAnimationDisabled"));
@@ -2373,8 +2374,10 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
finishSurfaceBehindRemoteAnimation(cancelled);
mSurfaceBehindRemoteAnimationRequested = false;
- mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation();
});
+
+ mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation(
+ cancelled);
}
/**
@@ -2412,8 +2415,16 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
return mSurfaceBehindRemoteAnimationRequested;
}
+ public boolean isAnimatingBetweenKeyguardAndSurfaceBehind() {
+ return mSurfaceBehindRemoteAnimationRunning;
+ }
+
/** If it's running, finishes the RemoteAnimation on the surface behind the keyguard. */
public void finishSurfaceBehindRemoteAnimation(boolean cancelled) {
+ if (!mSurfaceBehindRemoteAnimationRunning) {
+ return;
+ }
+
mSurfaceBehindRemoteAnimationRunning = false;
if (mSurfaceBehindRemoteAnimationFinishedCallback != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 60060aaf72da..00a314943f7a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -31,9 +31,9 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHE
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
-import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
@@ -83,6 +83,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBar;
@@ -97,7 +98,6 @@ import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -161,7 +161,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final CommandQueue mCommandQueue;
private final ShellTransitions mShellTransitions;
private final Optional<StartingSurface> mStartingSurface;
- private final SmartspaceTransitionController mSmartspaceTransitionController;
+ private final KeyguardUnlockAnimationController mSysuiUnlockAnimationController;
private final Optional<RecentTasks> mRecentTasks;
private final UiEventLogger mUiEventLogger;
@@ -503,8 +503,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
KEY_EXTRA_SHELL_STARTING_WINDOW,
startingwindow.createExternalInterface().asBinder()));
params.putBinder(
- KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER,
- mSmartspaceTransitionController.createExternalInterface().asBinder());
+ KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER,
+ mSysuiUnlockAnimationController.asBinder());
mRecentTasks.ifPresent(recentTasks -> params.putBinder(
KEY_EXTRA_RECENT_TASKS,
recentTasks.createExternalInterface().asBinder()));
@@ -570,8 +570,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
BroadcastDispatcher broadcastDispatcher,
ShellTransitions shellTransitions,
ScreenLifecycle screenLifecycle,
- SmartspaceTransitionController smartspaceTransitionController,
UiEventLogger uiEventLogger,
+ KeyguardUnlockAnimationController sysuiUnlockAnimationController,
DumpManager dumpManager) {
super(broadcastDispatcher);
mContext = context;
@@ -644,7 +644,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
updateEnabledState();
startConnectionToCurrentUser();
mStartingSurface = startingSurface;
- mSmartspaceTransitionController = smartspaceTransitionController;
+ mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/shared/system/smartspace/SmartspaceTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shared/system/smartspace/SmartspaceTransitionController.kt
deleted file mode 100644
index 89b3df0f495f..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shared/system/smartspace/SmartspaceTransitionController.kt
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2021 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.shared.system.smartspace
-
-import android.graphics.Rect
-import android.view.View
-import com.android.systemui.shared.system.ActivityManagerWrapper
-import com.android.systemui.shared.system.QuickStepContract
-import kotlin.math.min
-
-/**
- * Controller that keeps track of SmartSpace instances in remote processes (such as Launcher),
- * allowing System UI to query or update their state during shared-element transitions.
- */
-class SmartspaceTransitionController {
-
- /**
- * Implementation of [ISmartspaceTransitionController] that we provide to Launcher, allowing it
- * to provide us with a callback to query and update the state of its Smartspace.
- */
- private val ISmartspaceTransitionController = object : ISmartspaceTransitionController.Stub() {
- override fun setSmartspace(callback: ISmartspaceCallback?) {
- this@SmartspaceTransitionController.launcherSmartspace = callback
- updateLauncherSmartSpaceState()
- }
- }
-
- /**
- * Callback provided by Launcher to allow us to query and update the state of its SmartSpace.
- */
- public var launcherSmartspace: ISmartspaceCallback? = null
-
- public var lockscreenSmartspace: View? = null
-
- /**
- * Cached state of the Launcher SmartSpace. Retrieving the state is an IPC, so we should avoid
- * unnecessary
- */
- public var mLauncherSmartspaceState: SmartspaceState? = null
-
- /**
- * The bounds of our SmartSpace when the shared element transition began. We'll interpolate
- * between this and [smartspaceDestinationBounds] as the dismiss amount changes.
- */
- private val smartspaceOriginBounds = Rect()
-
- /** The bounds of the Launcher's SmartSpace, which is where we are animating our SmartSpace. */
-
- private val smartspaceDestinationBounds = Rect()
-
- fun createExternalInterface(): ISmartspaceTransitionController {
- return ISmartspaceTransitionController
- }
-
- /**
- * Updates [mLauncherSmartspaceState] and returns it. This will trigger a binder call, so use the
- * cached [mLauncherSmartspaceState] if possible.
- */
- fun updateLauncherSmartSpaceState(): SmartspaceState? {
- return launcherSmartspace?.smartspaceState.also {
- mLauncherSmartspaceState = it
- }
- }
-
- fun prepareForUnlockTransition() {
- updateLauncherSmartSpaceState().also { state ->
- if (state?.boundsOnScreen != null && lockscreenSmartspace != null) {
- lockscreenSmartspace!!.getBoundsOnScreen(smartspaceOriginBounds)
- with(smartspaceDestinationBounds) {
- set(state.boundsOnScreen)
- offset(-lockscreenSmartspace!!.paddingLeft,
- -lockscreenSmartspace!!.paddingTop)
- }
- }
- }
- }
-
- fun setProgressToDestinationBounds(progress: Float) {
- if (!isSmartspaceTransitionPossible()) {
- return
- }
-
- val progressClamped = min(1f, progress)
-
- // Calculate the distance (relative to the origin) that we need to be for the current
- // progress value.
- val progressX =
- (smartspaceDestinationBounds.left - smartspaceOriginBounds.left) * progressClamped
- val progressY =
- (smartspaceDestinationBounds.top - smartspaceOriginBounds.top) * progressClamped
-
- val lockscreenSmartspaceCurrentBounds = Rect().also {
- lockscreenSmartspace!!.getBoundsOnScreen(it)
- }
-
- // Figure out how far that is from our present location on the screen. This approach
- // compensates for the fact that our parent container is also translating to animate out.
- val dx = smartspaceOriginBounds.left + progressX -
- lockscreenSmartspaceCurrentBounds.left
- var dy = smartspaceOriginBounds.top + progressY -
- lockscreenSmartspaceCurrentBounds.top
-
- with(lockscreenSmartspace!!) {
- translationX = translationX + dx
- translationY = translationY + dy
- }
- }
-
- /**
- * Whether we're capable of performing the Smartspace shared element transition when we unlock.
- * This is true if:
- *
- * - The Launcher registered a Smartspace with us, it's reporting non-empty bounds on screen.
- * - Launcher is behind the keyguard, and the Smartspace is visible on the currently selected
- * page.
- */
- public fun isSmartspaceTransitionPossible(): Boolean {
- val smartSpaceNullOrBoundsEmpty = mLauncherSmartspaceState?.boundsOnScreen?.isEmpty ?: true
- return isLauncherUnderneath() && !smartSpaceNullOrBoundsEmpty
- }
-
- companion object {
- fun isLauncherUnderneath(): Boolean {
- return ActivityManagerWrapper.getInstance()
- .runningTask?.topActivity?.className?.equals(
- QuickStepContract.LAUNCHER_ACTIVITY_CLASS_NAME) ?: false
- }
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 46004db3067a..267ee6d2d177 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -154,6 +154,16 @@ class NotificationShadeDepthController @Inject constructor(
}
/**
+ * We're unlocking, and should not blur as the panel expansion changes.
+ */
+ var blursDisabledForUnlock: Boolean = false
+ set(value) {
+ if (field == value) return
+ field = value
+ scheduleUpdate()
+ }
+
+ /**
* Force stop blur effect when necessary.
*/
private var scrimsVisible: Boolean = false
@@ -192,7 +202,7 @@ class NotificationShadeDepthController @Inject constructor(
combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius)
- if (blursDisabledForAppLaunch) {
+ if (blursDisabledForAppLaunch || blursDisabledForUnlock) {
shadeRadius = 0f
}
@@ -309,9 +319,7 @@ class NotificationShadeDepthController @Inject constructor(
/**
* Update blurs when pulling down the shade
*/
- override fun onPanelExpansionChanged(
- rawFraction: Float, expanded: Boolean, tracking: Boolean
- ) {
+ override fun onPanelExpansionChanged(rawFraction: Float, expanded: Boolean, tracking: Boolean) {
val timestamp = SystemClock.elapsedRealtimeNanos()
val expansion = MathUtils.saturate(
(rawFraction - panelPullDownMinFraction) / (1f - panelPullDownMinFraction))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index dee1b334182a..8d500fa4e8b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -44,6 +44,7 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -254,6 +255,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
);
}
+ private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+
@Inject
public BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
@@ -269,7 +272,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
WakefulnessLifecycle wakefulnessLifecycle,
ScreenLifecycle screenLifecycle,
AuthController authController,
- StatusBarStateController statusBarStateController) {
+ StatusBarStateController statusBarStateController,
+ KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
mContext = context;
mPowerManager = powerManager;
mShadeController = shadeController;
@@ -292,6 +296,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mMetricsLogger = metricsLogger;
mAuthController = authController;
mStatusBarStateController = statusBarStateController;
+ mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
dumpManager.registerDumpable(getClass().getName(), this);
}
@@ -438,11 +443,15 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
if (!wasDeviceInteractive) {
mPendingShowBouncer = true;
} else {
- mShadeController.animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_NONE,
- true /* force */,
- false /* delayed */,
- BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
+ // If the keyguard unlock controller is going to handle the unlock animation, it
+ // will fling the panel collapsed when it's ready.
+ if (!mKeyguardUnlockAnimationController.willHandleUnlockAnimation()) {
+ mShadeController.animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_NONE,
+ true /* force */,
+ false /* delayed */,
+ BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
+ }
mPendingShowBouncer = false;
mKeyguardViewController.notifyKeyguardAuthenticated(
false /* strongAuth */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 016b953245b2..769f68976958 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -138,6 +138,7 @@ import com.android.systemui.fragments.FragmentService;
import com.android.systemui.idle.IdleHostView;
import com.android.systemui.idle.IdleHostViewController;
import com.android.systemui.idle.dagger.IdleViewComponent;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
@@ -791,7 +792,8 @@ public class NotificationPanelViewController extends PanelViewController {
Optional<SysUIUnfoldComponent> unfoldComponent,
ControlsComponent controlsComponent,
InteractionJankMonitor interactionJankMonitor,
- QsFrameTranslateController qsFrameTranslateController) {
+ QsFrameTranslateController qsFrameTranslateController,
+ KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
super(view,
featureFlags,
falsingManager,
@@ -806,7 +808,8 @@ public class NotificationPanelViewController extends PanelViewController {
lockscreenGestureLogger,
panelExpansionStateManager,
ambientState,
- interactionJankMonitor);
+ interactionJankMonitor,
+ keyguardUnlockAnimationController);
mView = view;
mVibratorHelper = vibratorHelper;
mKeyguardMediaController = keyguardMediaController;
@@ -925,8 +928,33 @@ public class NotificationPanelViewController extends PanelViewController {
mQsFrameTranslateController = qsFrameTranslateController;
updateUserSwitcherFlags();
onFinishInflate();
-
mUseCombinedQSHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS);
+ keyguardUnlockAnimationController.addKeyguardUnlockAnimationListener(
+ new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() {
+ @Override
+ public void onUnlockAnimationFinished() {
+ // Make sure the clock is in the correct position after the unlock animation
+ // so that it's not in the wrong place when we show the keyguard again.
+ positionClockAndNotifications(true /* forceClockUpdate */);
+ }
+
+ @Override
+ public void onUnlockAnimationStarted(
+ boolean playingCannedAnimation, boolean isWakeAndUnlock) {
+ // Disable blurs while we're unlocking so that panel expansion does not
+ // cause blurring. This will eventually be re-enabled by the panel view on
+ // ACTION_UP, since the user's finger might still be down after a swipe to
+ // unlock gesture, and we don't want that to cause blurring either.
+ mDepthController.setBlursDisabledForUnlock(mTracking);
+
+ if (playingCannedAnimation && !isWakeAndUnlock) {
+ // Fling the panel away so it's not in the way or the surface behind the
+ // keyguard, which will be appearing. If we're wake and unlocking, the
+ // lock screen is hidden instantly so should not be flung away.
+ fling(0f, false, 0.7f, false);
+ }
+ }
+ });
}
private void onFinishInflate() {
@@ -3324,6 +3352,10 @@ public class NotificationPanelViewController extends PanelViewController {
mAffordanceHelper.reset(true);
}
}
+
+ // If we unlocked from a swipe, the user's finger might still be down after the
+ // unlock animation ends. We need to wait until ACTION_UP to enable blurs again.
+ mDepthController.setBlursDisabledForUnlock(false);
}
private void updateMaxHeadsUpTranslation() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 53bfd7701335..05ac2a35c777 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -55,6 +55,7 @@ import com.android.systemui.classifier.Classifier;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -212,6 +213,8 @@ public abstract class PanelViewController {
return mAmbientState;
}
+ private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+
public PanelViewController(
PanelView view,
FeatureFlags featureFlags,
@@ -227,7 +230,15 @@ public abstract class PanelViewController {
LockscreenGestureLogger lockscreenGestureLogger,
PanelExpansionStateManager panelExpansionStateManager,
AmbientState ambientState,
- InteractionJankMonitor interactionJankMonitor) {
+ InteractionJankMonitor interactionJankMonitor,
+ KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
+ mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
+ keyguardStateController.addCallback(new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardFadingAwayChanged() {
+ requestPanelHeightUpdate();
+ }
+ });
mAmbientState = ambientState;
mView = view;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
@@ -437,7 +448,8 @@ public abstract class PanelViewController {
mUpdateFlingVelocity = vel;
}
} else if (!mStatusBar.isBouncerShowing()
- && !mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
+ && !mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()
+ && !mKeyguardStateController.isKeyguardGoingAway()) {
boolean expands = onEmptySpaceClick(mInitialTouchX);
onTrackingStopped(expands);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 5d83cc6259a0..48048b49e5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -809,6 +809,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
: ScrimState.SHADE_LOCKED.getBehindTint();
behindTint = ColorUtils.blendARGB(behindTint, stateTint, mQsExpansion);
}
+
+ // If the keyguard is going away, we should not be opaque.
+ if (mKeyguardStateController.isKeyguardGoingAway()) {
+ behindAlpha = 0f;
+ }
+
return new Pair<>(behindTint, behindAlpha);
}
@@ -1333,9 +1339,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
mExpansionAffectsAlpha = expansionAffectsAlpha;
- if (expansionAffectsAlpha) {
- applyAndDispatchState();
- }
}
public void setKeyguardOccluded(boolean keyguardOccluded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9a9e3bc58774..ae4a19e2b212 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2978,6 +2978,8 @@ public class StatusBar extends CoreStartable implements
public void showKeyguardImpl() {
mIsKeyguard = true;
+ // In case we're locking while a smartspace transition is in progress, reset it.
+ mKeyguardUnlockAnimationController.resetSmartspaceTransition();
if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
mNotificationPanelViewController.cancelAnimation();
onLaunchTransitionFadingEnded();
@@ -3156,6 +3158,7 @@ public class StatusBar extends CoreStartable implements
// bar.
mKeyguardStateController.notifyKeyguardGoingAway(true);
mCommandQueue.appTransitionPending(mDisplayId, true /* forced */);
+ updateScrimController();
}
/**
@@ -3327,7 +3330,10 @@ public class StatusBar extends CoreStartable implements
}
private void showBouncerOrLockScreenIfKeyguard() {
- if (!mKeyguardViewMediator.isHiding()) {
+ // If the keyguard is animating away, we aren't really the keyguard anymore and should not
+ // show the bouncer/lockscreen.
+ if (!mKeyguardViewMediator.isHiding()
+ && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
if (mState == StatusBarState.SHADE_LOCKED
&& mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
// shade is showing while locked on the keyguard, so go back to showing the
@@ -3761,17 +3767,14 @@ public class StatusBar extends CoreStartable implements
public void updateScrimController() {
Trace.beginSection("StatusBar#updateScrimController");
- // We don't want to end up in KEYGUARD state when we're unlocking with
- // fingerprint from doze. We should cross fade directly from black.
- boolean unlocking = mBiometricUnlockController.isWakeAndUnlock()
- || mKeyguardStateController.isKeyguardFadingAway();
+ boolean unlocking = mKeyguardStateController.isShowing() && (
+ mBiometricUnlockController.isWakeAndUnlock()
+ || mKeyguardStateController.isKeyguardFadingAway()
+ || mKeyguardStateController.isKeyguardGoingAway()
+ || mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard()
+ || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
- // Do not animate the scrim expansion when triggered by the fingerprint sensor.
- boolean onKeyguardOrHidingIt = mKeyguardStateController.isShowing()
- || mKeyguardStateController.isKeyguardFadingAway()
- || mKeyguardStateController.isKeyguardGoingAway();
- mScrimController.setExpansionAffectsAlpha(!(mBiometricUnlockController.isBiometricUnlock()
- && onKeyguardOrHidingIt));
+ mScrimController.setExpansionAffectsAlpha(!unlocking);
boolean launchingAffordanceWithPreview =
mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
@@ -3783,7 +3786,7 @@ public class StatusBar extends CoreStartable implements
} else {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
}
- } else if (mBouncerShowing) {
+ } else if (mBouncerShowing && !unlocking) {
// Bouncer needs the front scrim when it's on top of an activity,
// tapping on a notification, editing QS or being dismissed by
// FLAG_DISMISS_KEYGUARD_ACTIVITY.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
index 7bf1601b2fd5..050b67016d09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
@@ -50,13 +50,6 @@ public interface KeyguardStateController extends CallbackController<Callback> {
boolean canDismissLockScreen();
/**
- * Whether we can currently perform the shared element SmartSpace transition. This is true if
- * we're on the lockscreen, it can be dismissed with a swipe, and the Launcher is underneath the
- * keyguard and displaying a SmartSpace that it has registered with System UI.
- */
- boolean canPerformSmartSpaceTransition();
-
- /**
* Whether the keyguard is allowed to rotate, or needs to be locked to the default orientation.
*/
boolean isKeyguardScreenRotationAllowed();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 05a586b1cdc2..978564fc81d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -35,7 +35,7 @@ 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.shared.system.smartspace.SmartspaceTransitionController;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,6 +44,8 @@ import java.util.Objects;
import javax.inject.Inject;
+import dagger.Lazy;
+
/**
*/
@SysUISingleton
@@ -58,7 +60,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
private final LockPatternUtils mLockPatternUtils;
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new UpdateMonitorCallback();
- private final SmartspaceTransitionController mSmartspaceTransitionController;
+ private final Lazy<KeyguardUnlockAnimationController> mUnlockAnimationControllerLazy;
private boolean mCanDismissLockScreen;
private boolean mShowing;
@@ -105,13 +107,13 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
Context context,
KeyguardUpdateMonitor keyguardUpdateMonitor,
LockPatternUtils lockPatternUtils,
- SmartspaceTransitionController smartspaceTransitionController,
+ Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController,
DumpManager dumpManager) {
mContext = context;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
- mSmartspaceTransitionController = smartspaceTransitionController;
+ mUnlockAnimationControllerLazy = keyguardUnlockAnimationController;
dumpManager.registerDumpable(getClass().getSimpleName(), this);
@@ -249,12 +251,6 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
}
@Override
- public boolean canPerformSmartSpaceTransition() {
- return canDismissLockScreen()
- && mSmartspaceTransitionController.isSmartspaceTransitionPossible();
- }
-
- @Override
public boolean isKeyguardScreenRotationAllowed() {
return SystemProperties.getBoolean("lockscreen.rot_override", false)
|| mContext.getResources().getBoolean(R.bool.config_enableLockScreenRotation);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 74e0f4002026..c2439df6624a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -48,7 +48,6 @@ import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -96,9 +95,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
@Mock
Resources mResources;
- KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock
- SmartspaceTransitionController mSmartSpaceTransitionController;
+ KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock
private ClockPlugin mClockPlugin;
@Mock
@@ -154,7 +152,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
mBypassController,
mSmartspaceController,
mKeyguardUnlockAnimationController,
- mSmartSpaceTransitionController,
mSecureSettings,
mExecutor,
mResources
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 80de24868181..217092e6e4e5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -24,7 +24,6 @@ import android.testing.AndroidTestingRunner;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.communal.CommunalStateController;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -61,8 +60,6 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
@Mock
KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock
- SmartspaceTransitionController mSmartSpaceTransitionController;
- @Mock
ScreenOffAnimationController mScreenOffAnimationController;
@Captor
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@@ -83,7 +80,6 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
mConfigurationController,
mDozeParameters,
mKeyguardUnlockAnimationController,
- mSmartSpaceTransitionController,
mScreenOffAnimationController);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
index f3043e934c8a..fb1a968acceb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
@@ -14,7 +14,6 @@ import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardViewController
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
import junit.framework.Assert.assertEquals
@@ -44,8 +43,6 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
@Mock
private lateinit var keyguardViewController: KeyguardViewController
@Mock
- private lateinit var smartspaceTransitionController: SmartspaceTransitionController
- @Mock
private lateinit var featureFlags: FeatureFlags
@Mock
private lateinit var biometricUnlockController: BiometricUnlockController
@@ -59,7 +56,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
keyguardUnlockAnimationController = KeyguardUnlockAnimationController(
context, keyguardStateController, { keyguardViewMediator }, keyguardViewController,
- smartspaceTransitionController, featureFlags, biometricUnlockController
+ featureFlags, { biometricUnlockController }
)
`when`(keyguardViewController.viewRootImpl).thenReturn(mock(ViewRootImpl::class.java))
@@ -87,7 +84,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
fun noSurfaceAnimation_ifWakeAndUnlocking() {
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
- keyguardUnlockAnimationController.notifyStartKeyguardExitAnimation(
+ keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTarget,
0 /* startTime */,
false /* requestedShowSurfaceBehindKeyguard */
@@ -118,15 +115,12 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
fun surfaceAnimation_ifNotWakeAndUnlocking() {
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(false)
- keyguardUnlockAnimationController.notifyStartKeyguardExitAnimation(
+ keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation(
remoteAnimationTarget,
0 /* startTime */,
false /* requestedShowSurfaceBehindKeyguard */
)
- // Make sure the animator was started.
- assertTrue(keyguardUnlockAnimationController.surfaceBehindEntryAnimator.isRunning)
-
// Since the animation is running, we should not have finished the remote animation.
verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished(
false /* cancelled */)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 0bce621c3b02..91e5d33d9c9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -302,6 +302,40 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() {
}
@Test
+ fun ignoreBlurForUnlock_ignores() {
+ notificationShadeDepthController.onPanelExpansionChanged(
+ rawFraction = 1f, expanded = true, tracking = false
+ )
+ `when`(shadeAnimation.radius).thenReturn(maxBlur.toFloat())
+
+ notificationShadeDepthController.blursDisabledForAppLaunch = false
+ notificationShadeDepthController.blursDisabledForUnlock = true
+
+ notificationShadeDepthController.updateBlurCallback.doFrame(0)
+
+ // Since we are ignoring blurs for unlock, we should be applying blur = 0 despite setting it
+ // to maxBlur above.
+ verify(blurUtils).applyBlur(any(), eq(0), eq(false))
+ }
+
+ @Test
+ fun ignoreBlurForUnlock_doesNotIgnore() {
+ notificationShadeDepthController.onPanelExpansionChanged(
+ rawFraction = 1f, expanded = true, tracking = false
+ )
+ `when`(shadeAnimation.radius).thenReturn(maxBlur.toFloat())
+
+ notificationShadeDepthController.blursDisabledForAppLaunch = false
+ notificationShadeDepthController.blursDisabledForUnlock = false
+
+ notificationShadeDepthController.updateBlurCallback.doFrame(0)
+
+ // Since we are not ignoring blurs for unlock (or app launch), we should apply the blur we
+ // returned above (maxBlur).
+ verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
+ }
+
+ @Test
fun brightnessMirrorVisible_whenVisible() {
notificationShadeDepthController.brightnessMirrorVisible = true
verify(brightnessSpring).animateTo(eq(maxBlur), any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 1961ab269267..188baaf682b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -561,6 +561,10 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
override fun setMediaTarget(target: SmartspaceTarget?) {
}
+
+ override fun getSelectedPage(): Int {
+ return -1
+ }
})
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index c3349f1d70f4..5ca1f21eb021 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -42,6 +42,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -104,6 +105,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
private ScreenLifecycle mScreenLifecycle;
@Mock
private StatusBarStateController mStatusBarStateController;
+ @Mock
+ private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private BiometricUnlockController mBiometricUnlockController;
@Before
@@ -126,7 +129,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters,
mMetricsLogger, mDumpManager, mPowerManager,
mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
- mAuthController, mStatusBarStateController);
+ mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 35f671bf8298..1c8b35aeaeaf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -104,6 +104,7 @@ import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.idle.IdleHostViewController;
import com.android.systemui.idle.dagger.IdleViewComponent;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
@@ -362,6 +363,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
private QsFrameTranslateController mQsFrameTranslateController;
@Mock
private StatusBarWindowStateController mStatusBarWindowStateController;
+ @Mock
+ private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -546,7 +549,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mSysUIUnfoldComponent,
mControlsComponent,
mInteractionJankMonitor,
- mQsFrameTranslateController);
+ mQsFrameTranslateController,
+ mKeyguardUnlockAnimationController);
mNotificationPanelViewController.initDependencies(
mStatusBar,
() -> {},
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index bb8bad39ab31..77065b2d4380 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -819,31 +819,27 @@ public class StatusBarTest extends SysuiTestCase {
}
@Test
- public void testSetExpansionAffectsAlpha_onlyWhenHidingKeyguard() {
+ public void testSetExpansionAffectsAlpha_whenKeyguardShowingButGoingAwayForAnyReason() {
mStatusBar.updateScrimController();
verify(mScrimController).setExpansionAffectsAlpha(eq(true));
clearInvocations(mScrimController);
- when(mBiometricUnlockController.isBiometricUnlock()).thenReturn(true);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
mStatusBar.updateScrimController();
verify(mScrimController).setExpansionAffectsAlpha(eq(true));
clearInvocations(mScrimController);
when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
mStatusBar.updateScrimController();
verify(mScrimController).setExpansionAffectsAlpha(eq(false));
clearInvocations(mScrimController);
- reset(mKeyguardStateController);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
mStatusBar.updateScrimController();
verify(mScrimController).setExpansionAffectsAlpha(eq(false));
-
- clearInvocations(mScrimController);
- reset(mKeyguardStateController);
- when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
- mStatusBar.updateScrimController();
- verify(mScrimController).setExpansionAffectsAlpha(eq(false));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
index 8ccaf9362454..4a8170fc2955 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
@@ -33,7 +33,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import org.junit.Before;
import org.junit.Test;
@@ -41,6 +41,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import dagger.Lazy;
+
@SmallTest
@TestableLooper.RunWithLooper
@RunWith(AndroidTestingRunner.class)
@@ -52,9 +54,9 @@ public class KeyguardStateControllerTest extends SysuiTestCase {
private LockPatternUtils mLockPatternUtils;
private KeyguardStateController mKeyguardStateController;
@Mock
- private SmartspaceTransitionController mSmartSpaceTransitionController;
- @Mock
private DumpManager mDumpManager;
+ @Mock
+ private Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy;
@Before
public void setup() {
@@ -63,7 +65,7 @@ public class KeyguardStateControllerTest extends SysuiTestCase {
mContext,
mKeyguardUpdateMonitor,
mLockPatternUtils,
- mSmartSpaceTransitionController,
+ mKeyguardUnlockAnimationControllerLazy,
mDumpManager);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
index e136d00b86f8..aaea4ecdc08d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
@@ -129,11 +129,6 @@ public class FakeKeyguardStateController implements KeyguardStateController {
}
@Override
- public boolean canPerformSmartSpaceTransition() {
- return false;
- }
-
- @Override
public boolean isKeyguardScreenRotationAllowed() {
return false;
}