diff options
21 files changed, 572 insertions, 22 deletions
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp index f98a959346d3..b2ae2a0ca8ad 100644 --- a/packages/SystemUI/shared/Android.bp +++ b/packages/SystemUI/shared/Android.bp @@ -40,7 +40,8 @@ android_library { name: "SystemUISharedLib", srcs: [ "src/**/*.java", - "src/**/I*.aidl", + "src/**/*.kt", + "src/**/*.aidl", ":wm_shell-aidls", ], 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 2cf3ad2dcd49..c468e416f8a5 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 @@ -36,6 +36,9 @@ import java.util.StringJoiner; * Various shared constants between Launcher and SysUI as part of quickstep */ public class QuickStepContract { + // Fully qualified name of the Launcher activity. + public static final String LAUNCHER_ACTIVITY_CLASS_NAME = + "com.google.android.apps.nexuslauncher.NexusLauncherActivity"; public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy"; public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius"; @@ -52,6 +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"; public static final String NAV_BAR_MODE_2BUTTON_OVERLAY = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY; 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 new file mode 100644 index 000000000000..511df4c285b4 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceCallback.aidl @@ -0,0 +1,34 @@ +/* + * 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 new file mode 100644 index 000000000000..2b3e961ab3b2 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ISmartspaceTransitionController.aidl @@ -0,0 +1,24 @@ +/* + * 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/SmartspaceState.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.aidl new file mode 100644 index 000000000000..2d01d6af63c5 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.aidl @@ -0,0 +1,21 @@ +/* + * 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; + +parcelable SmartspaceState;
\ 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 new file mode 100644 index 000000000000..2d51c4d13611 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt @@ -0,0 +1,59 @@ +/* + * 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.os.Parcel +import android.os.Parcelable + +/** + * Represents the state of a SmartSpace, including its location on screen and the index of the + * currently selected page. This object contains all of the information needed to synchronize two + * SmartSpace instances so that we can perform shared-element transitions between them. + */ +class SmartspaceState() : Parcelable { + var boundsOnScreen: Rect = Rect() + var selectedPage = 0 + + constructor(parcel: Parcel) : this() { + this.boundsOnScreen = parcel.readParcelable(Rect::javaClass.javaClass.classLoader) + this.selectedPage = parcel.readInt() + } + + override fun writeToParcel(dest: Parcel?, flags: Int) { + dest?.writeParcelable(boundsOnScreen, 0) + dest?.writeInt(selectedPage) + } + + override fun describeContents(): Int { + return 0 + } + + override fun toString(): String { + return "boundsOnScreen: $boundsOnScreen, selectedPage: $selectedPage" + } + + companion object CREATOR : Parcelable.Creator<SmartspaceState> { + override fun createFromParcel(parcel: Parcel): SmartspaceState { + return SmartspaceState(parcel) + } + + override fun newArray(size: Int): Array<SmartspaceState?> { + return arrayOfNulls(size) + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 932860f6c29c..bc23481114a3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -32,8 +32,10 @@ import com.android.keyguard.clock.ClockManager; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; 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.lockscreen.LockscreenSmartspaceController; import com.android.systemui.statusbar.notification.AnimatableProperty; import com.android.systemui.statusbar.notification.PropertyAnimator; @@ -44,7 +46,9 @@ import com.android.systemui.statusbar.phone.NotificationIconContainer; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.util.ViewController; +import java.util.HashSet; import java.util.Locale; +import java.util.Set; import java.util.TimeZone; import javax.inject.Inject; @@ -92,6 +96,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS // If set, will replace keyguard_status_area private View mSmartspaceView; + private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + private SmartspaceTransitionController mSmartspaceTransitionController; + @Inject public KeyguardClockSwitchController( KeyguardClockSwitch keyguardClockSwitch, @@ -104,7 +111,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS BatteryController batteryController, KeyguardUpdateMonitor keyguardUpdateMonitor, KeyguardBypassController bypassController, - LockscreenSmartspaceController smartspaceController) { + LockscreenSmartspaceController smartspaceController, + KeyguardUnlockAnimationController keyguardUnlockAnimationController, + SmartspaceTransitionController smartspaceTransitionController) { super(keyguardClockSwitch); mStatusBarStateController = statusBarStateController; mColorExtractor = colorExtractor; @@ -116,6 +125,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mKeyguardUpdateMonitor = keyguardUpdateMonitor; mBypassController = bypassController; mSmartspaceController = smartspaceController; + + mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; + mSmartspaceTransitionController = smartspaceTransitionController; } /** @@ -187,6 +199,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS nic.setLayoutParams(lp); mView.setSmartspaceView(mSmartspaceView); + mSmartspaceTransitionController.setLockscreenSmartspace(mSmartspaceView); } } @@ -282,12 +295,44 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS if (mSmartspaceView != null) { PropertyAnimator.setProperty(mSmartspaceView, AnimatableProperty.TRANSLATION_X, x, props, animate); + + // If we're unlocking with the SmartSpace shared element transition, let the controller + // know that it should re-position our SmartSpace. + if (mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) { + mKeyguardUnlockAnimationController.updateLockscreenSmartSpacePosition(); + } else { + // Otherwise, reset Y translation in case it's still offset from a previous shared + // element transition. + ((View) mSmartspaceView).setTranslationY(0f); + } } mKeyguardSliceViewController.updatePosition(x, props, animate); mNotificationIconAreaController.updatePosition(x, props, animate); } + /** Sets an alpha value on every child view except for the smartspace. */ + public void setChildrenAlphaExcludingSmartspace(float alpha) { + final Set<View> excludedViews = new HashSet<>(); + + if (mSmartspaceView != null) { + excludedViews.add(mSmartspaceView); + } + + setChildrenAlphaExcluding(alpha, excludedViews); + } + + /** Sets an alpha value on every child view except for the views in the provided set. */ + public void setChildrenAlphaExcluding(float alpha, Set<View> excludedViews) { + for (int i = 0; i < mView.getChildCount(); i++) { + final View child = mView.getChildAt(i); + + if (!excludedViews.contains(child)) { + child.setAlpha(alpha); + } + } + } + void updateTimeZone(TimeZone timeZone) { mView.onTimeZoneChanged(timeZone); if (mClockViewController != null) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index 3ab2cca09a29..250f598d0ca3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -28,6 +28,7 @@ import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; +import android.view.ViewGroup; import android.widget.GridLayout; import android.widget.TextView; @@ -39,6 +40,7 @@ import com.android.systemui.statusbar.CrossFadeHelper; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Set; /** * View consisting of: @@ -55,6 +57,7 @@ public class KeyguardStatusView extends GridLayout { private final LockPatternUtils mLockPatternUtils; private final IActivityManager mIActivityManager; + private ViewGroup mStatusViewContainer; private TextView mLogoutView; private KeyguardClockSwitch mClockView; private TextView mOwnerInfo; @@ -66,6 +69,7 @@ public class KeyguardStatusView extends GridLayout { private float mDarkAmount = 0; private int mTextColor; + private float mChildrenAlphaExcludingSmartSpace = 1f; /** * Bottom margin that defines the margin between bottom of smart space and top of notification @@ -132,6 +136,7 @@ public class KeyguardStatusView extends GridLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); + mStatusViewContainer = findViewById(R.id.status_view_container); mLogoutView = findViewById(R.id.logout); if (mLogoutView != null) { mLogoutView.setOnClickListener(this::onLogoutClicked); @@ -251,6 +256,27 @@ public class KeyguardStatusView extends GridLayout { mClockView.setTextColor(blendedTextColor); } + public void setChildrenAlphaExcludingClockView(float alpha) { + setChildrenAlphaExcluding(alpha, Set.of(mClockView)); + } + + /** Sets an alpha value on every view except for the views in the provided set. */ + public void setChildrenAlphaExcluding(float alpha, Set<View> excludedViews) { + mChildrenAlphaExcludingSmartSpace = alpha; + + for (int i = 0; i < mStatusViewContainer.getChildCount(); i++) { + final View child = mStatusViewContainer.getChildAt(i); + + if (!excludedViews.contains(child)) { + child.setAlpha(alpha); + } + } + } + + public float getChildrenAlphaExcludingSmartSpace() { + return mChildrenAlphaExcludingSmartSpace; + } + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("KeyguardStatusView:"); pw.println(" mOwnerInfo: " + (mOwnerInfo == null diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 388c085fd1a0..7b6514a63195 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -20,6 +20,8 @@ import android.graphics.Rect; import android.os.UserHandle; import android.util.Slog; +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; @@ -49,6 +51,9 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV private final ConfigurationController mConfigurationController; private final DozeParameters mDozeParameters; private final KeyguardVisibilityHelper mKeyguardVisibilityHelper; + private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + private final KeyguardStateController mKeyguardStateController; + private SmartspaceTransitionController mSmartspaceTransitionController; private final Rect mClipBounds = new Rect(); @Inject @@ -59,15 +64,33 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV KeyguardStateController keyguardStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, ConfigurationController configurationController, - DozeParameters dozeParameters) { + DozeParameters dozeParameters, + KeyguardUnlockAnimationController keyguardUnlockAnimationController, + SmartspaceTransitionController smartspaceTransitionController) { super(keyguardStatusView); mKeyguardSliceViewController = keyguardSliceViewController; mKeyguardClockSwitchController = keyguardClockSwitchController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mConfigurationController = configurationController; mDozeParameters = dozeParameters; + mKeyguardStateController = keyguardStateController; mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController, dozeParameters); + mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; + mSmartspaceTransitionController = smartspaceTransitionController; + + mKeyguardStateController.addCallback(new KeyguardStateController.Callback() { + @Override + public void onKeyguardShowingChanged() { + // If we explicitly re-show the keyguard, make sure that all the child views are + // visible. They might have been animating out as part of the SmartSpace shared + // element transition. + if (keyguardStateController.isShowing()) { + mView.setChildrenAlphaExcludingClockView(1f); + mKeyguardClockSwitchController.setChildrenAlphaExcludingSmartspace(1f); + } + } + }); } @Override @@ -137,7 +160,24 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV */ public void setAlpha(float alpha) { if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) { - mView.setAlpha(alpha); + // If we're capable of performing the SmartSpace shared element transition, and we are + // going to (we're swiping to dismiss vs. bringing up the PIN screen), then fade out + // everything except for the SmartSpace. + if (mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) { + mView.setChildrenAlphaExcludingClockView(alpha); + mKeyguardClockSwitchController.setChildrenAlphaExcludingSmartspace(alpha); + } else if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) { + // Otherwise, we can just set the alpha for the entire container. + mView.setAlpha(alpha); + + // If we previously unlocked with the shared element transition, some child views + // might still have alpha = 0f. Set them back to 1f since we're just using the + // parent container's alpha. + if (mView.getChildrenAlphaExcludingSmartSpace() < 1f) { + mView.setChildrenAlphaExcludingClockView(1f); + mKeyguardClockSwitchController.setChildrenAlphaExcludingSmartspace(1f); + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index cc167b928c3c..e6fe0600b9b8 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -133,6 +133,7 @@ public class SystemUIFactory { .setTaskViewFactory(Optional.ofNullable(null)) .setTransitions(Transitions.createEmptyForTesting()) .setStartingSurface(Optional.ofNullable(null)); + } mSysUIComponent = builder.build(); if (mInitializeComponents) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 1396099db948..f422e9e40d33 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -45,6 +45,7 @@ import com.android.systemui.power.dagger.PowerModule; 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.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -173,6 +174,12 @@ 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/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index 411c328cd310..665376ac4569 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -23,11 +23,14 @@ import android.content.Context import android.graphics.Matrix import android.view.RemoteAnimationTarget import android.view.SyncRtSurfaceTransactionApplier +import android.view.View import androidx.core.math.MathUtils import com.android.internal.R +import com.android.keyguard.KeyguardClockSwitchController import com.android.keyguard.KeyguardViewController import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController import com.android.systemui.statusbar.policy.KeyguardStateController import dagger.Lazy import javax.inject.Inject @@ -85,7 +88,8 @@ class KeyguardUnlockAnimationController @Inject constructor( context: Context, private val keyguardStateController: KeyguardStateController, private val keyguardViewMediator: Lazy<KeyguardViewMediator>, - private val keyguardViewController: KeyguardViewController + private val keyguardViewController: KeyguardViewController, + private val smartspaceTransitionController: SmartspaceTransitionController ) : KeyguardStateController.Callback { /** @@ -131,6 +135,21 @@ 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 are currently in the process of unlocking the keyguard, and we are performing the + * shared element SmartSpace transition. + */ + private var unlockingWithSmartSpaceTransition: Boolean = false + + /** + * 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). + */ + private var attemptedSmartSpaceTransitionForThisSwipe = false + init { surfaceBehindAlphaAnimator.duration = 150 surfaceBehindAlphaAnimator.interpolator = Interpolators.ALPHA_IN @@ -214,6 +233,24 @@ class KeyguardUnlockAnimationController @Inject constructor( } /** + * 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 + } + + /** + * 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). + */ + fun updateLockscreenSmartSpacePosition() { + smartspaceTransitionController.setProgressToDestinationBounds( + keyguardStateController.dismissAmount / DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD) + } + + /** * Scales in and translates up the surface behind the keyguard. This is used during unlock * animations and swipe gestures to animate the surface's entry (and exit, if the swipe is * cancelled). @@ -284,36 +321,85 @@ class KeyguardUnlockAnimationController @Inject constructor( return } + if (keyguardViewController.isShowing) { + updateKeyguardViewMediatorIfThresholdsReached() + + // 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) { + updateSurfaceBehindAppearAmount() + } + } + + // 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() + } + + /** + * Lets the KeyguardViewMediator know if the dismiss amount has crossed a threshold of interest, + * such as reaching the point in the dismiss swipe where we need to make the surface behind the + * keyguard visible. + */ + private fun updateKeyguardViewMediatorIfThresholdsReached() { val dismissAmount = keyguardStateController.dismissAmount // Hide the keyguard if we're fully dismissed, or if we're swiping to dismiss and have // crossed the threshold to finish the dismissal. val reachedHideKeyguardThreshold = (dismissAmount >= 1f || (keyguardStateController.isDismissingFromSwipe && - // Don't hide if we're flinging during a swipe, since we need to finish - // animating it out. This will be called again after the fling ends. - !keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture && - dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) + // Don't hide if we're flinging during a swipe, since we need to finish + // animating it out. This will be called again after the fling ends. + !keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture && + dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) 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. + // We passed the threshold, and we're not yet showing the surface behind the + // keyguard. Animate it in. keyguardViewMediator.get().showSurfaceBehindKeyguard() fadeInSurfaceBehind() } else if (dismissAmount < DISMISS_AMOUNT_SHOW_SURFACE_THRESHOLD && keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard()) { - // We're no longer past the threshold but we are showing the surface. Animate it out. + // We're no longer past the threshold but we are showing the surface. Animate it + // out. keyguardViewMediator.get().hideSurfaceBehindKeyguard() fadeOutSurfaceBehind() - } else if (keyguardViewMediator.get().isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe && + } else if (keyguardViewMediator.get() + .isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe && reachedHideKeyguardThreshold) { keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished() } + } - if (keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard() || - keyguardViewMediator.get().isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe) { - updateSurfaceBehindAppearAmount() + /** + * Updates flags related to the SmartSpace transition in response to a change in keyguard + * dismiss amount, and also updates the SmartSpaceTransitionController, which will let Launcher + * know if it needs to do something as a result. + */ + private fun updateSmartSpaceTransition() { + val dismissAmount = keyguardStateController.dismissAmount + + // If we've begun a swipe, and are capable of doing the SmartSpace transition, start it! + if (!attemptedSmartSpaceTransitionForThisSwipe && + dismissAmount > 0f && + dismissAmount < 1f && + keyguardViewController.isShowing) { + attemptedSmartSpaceTransitionForThisSwipe = true + + smartspaceTransitionController.prepareForUnlockTransition() + if (keyguardStateController.canPerformSmartSpaceTransition()) { + unlockingWithSmartSpaceTransition = true + smartspaceTransitionController.launcherSmartspace?.setVisibility( + View.INVISIBLE) + } + } else if (attemptedSmartSpaceTransitionForThisSwipe && + (dismissAmount == 0f || dismissAmount == 1f)) { + attemptedSmartSpaceTransitionForThisSwipe = false + unlockingWithSmartSpaceTransition = false + smartspaceTransitionController.launcherSmartspace?.setVisibility(View.VISIBLE) } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 20c3e818e097..6a07a000045b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -29,6 +29,7 @@ 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_WINDOW_CORNER_RADIUS; @@ -88,6 +89,7 @@ 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.StatusBar; @@ -148,6 +150,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 Region mActiveNavBarRegion; @@ -540,6 +543,9 @@ public class OverviewProxyService extends CurrentUserTracker implements mStartingSurface.ifPresent((startingwindow) -> params.putBinder( KEY_EXTRA_SHELL_STARTING_WINDOW, startingwindow.createExternalInterface().asBinder())); + params.putBinder( + KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER, + mSmartspaceTransitionController.createExternalInterface().asBinder()); try { Log.d(TAG_OPS + " b/182478748", "OverviewProxyService.onInitialize: curUser=" @@ -601,7 +607,8 @@ public class OverviewProxyService extends CurrentUserTracker implements Optional<OneHanded> oneHandedOptional, BroadcastDispatcher broadcastDispatcher, ShellTransitions shellTransitions, - Optional<StartingSurface> startingSurface) { + Optional<StartingSurface> startingSurface, + SmartspaceTransitionController smartspaceTransitionController) { super(broadcastDispatcher); mContext = context; mPipOptional = pipOptional; @@ -663,6 +670,7 @@ public class OverviewProxyService extends CurrentUserTracker implements updateEnabledState(); startConnectionToCurrentUser(); mStartingSurface = startingSurface; + mSmartspaceTransitionController = smartspaceTransitionController; } @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 new file mode 100644 index 000000000000..89b3df0f495f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shared/system/smartspace/SmartspaceTransitionController.kt @@ -0,0 +1,143 @@ +/* + * 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/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index ec012bfde9b8..6f1ab0e2ca64 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -456,6 +456,7 @@ public class StatusBar extends SystemUI implements DemoMode, protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider; private final BrightnessSlider.Factory mBrightnessSliderFactory; private final FeatureFlags mFeatureFlags; + private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private final List<ExpansionChangedListener> mExpansionChangedListeners; @@ -877,6 +878,8 @@ public class StatusBar extends SystemUI implements DemoMode, mAnimationScheduler = animationScheduler; mStatusBarLocationPublisher = locationPublisher; mFeatureFlags = featureFlags; + mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; + mLockscreenShadeTransitionController = lockscreenShadeTransitionController; lockscreenShadeTransitionController.setStatusbar(this); @@ -1365,7 +1368,8 @@ public class StatusBar extends SystemUI implements DemoMode, // are already animating the keyguard dismiss (since we will need to either finish or cancel // the animation). if (trackingTouch - || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()) { + || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe() + || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) { mKeyguardStateController.notifyKeyguardDismissAmountChanged( 1f - expansion, trackingTouch); } 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 e7201f87b320..af7bf9500bf3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java @@ -50,6 +50,13 @@ 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(); + + /** * If the device has PIN/pattern/password or a lock screen at all. */ boolean isMethodSecure(); 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 e69c1f2573b7..0945a3f884d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -32,6 +32,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -53,6 +54,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum private final LockPatternUtils mLockPatternUtils; private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = new UpdateMonitorCallback(); + private final SmartspaceTransitionController mSmartspaceTransitionController; private boolean mCanDismissLockScreen; private boolean mShowing; @@ -96,10 +98,12 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum */ @Inject public KeyguardStateControllerImpl(Context context, - KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) { + KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, + SmartspaceTransitionController smartspaceTransitionController) { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); + mSmartspaceTransitionController = smartspaceTransitionController; update(true /* updateAlways */); if (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB) { @@ -158,6 +162,11 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum mShowing = showing; mOccluded = occluded; notifyKeyguardChanged(); + + // Update the dismiss amount to the full 0f/1f if we explicitly show or hide the keyguard. + // Otherwise, the dismiss amount could be left at a random value if we show/hide during a + // dismiss gesture, canceling the gesture. + notifyKeyguardDismissAmountChanged(showing ? 0f : 1f, false); } private void notifyKeyguardChanged() { @@ -228,6 +237,12 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum } @Override + public boolean canPerformSmartSpaceTransition() { + return canDismissLockScreen() + && mSmartspaceTransitionController.isSmartspaceTransitionPossible(); + } + + @Override public boolean isFaceAuthEnabled() { return mFaceAuthEnabled; } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index 98467d4816b8..1111e706cbfe 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -40,8 +40,10 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; 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; @@ -86,6 +88,9 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { @Mock Resources mResources; + KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + @Mock + SmartspaceTransitionController mSmartSpaceTransitionController; @Mock private ClockPlugin mClockPlugin; @Mock @@ -135,7 +140,10 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { mBatteryController, mKeyguardUpdateMonitor, mBypassController, - mSmartspaceController); + mSmartspaceController, + mKeyguardUnlockAnimationController, + mSmartSpaceTransitionController + ); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java index 49f1655997ef..f9b6d4467e3c 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java @@ -22,6 +22,8 @@ import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import com.android.systemui.SysuiTestCase; +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.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -50,6 +52,10 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase { ConfigurationController mConfigurationController; @Mock DozeParameters mDozeParameters; + @Mock + KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + @Mock + SmartspaceTransitionController mSmartSpaceTransitionController; private KeyguardStatusViewController mController; @@ -64,7 +70,9 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase { mKeyguardStateController, mKeyguardUpdateMonitor, mConfigurationController, - mDozeParameters); + mDozeParameters, + mKeyguardUnlockAnimationController, + mSmartSpaceTransitionController); } @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 53a2efce9bb8..4b87ec895773 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 @@ -32,6 +32,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; +import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController; import org.junit.Before; import org.junit.Test; @@ -49,12 +50,14 @@ public class KeyguardStateControllerTest extends SysuiTestCase { @Mock private LockPatternUtils mLockPatternUtils; private KeyguardStateController mKeyguardStateController; + @Mock + private SmartspaceTransitionController mSmartSpaceTransitionController; @Before public void setup() { MockitoAnnotations.initMocks(this); mKeyguardStateController = new KeyguardStateControllerImpl(mContext, - mKeyguardUpdateMonitor, mLockPatternUtils); + mKeyguardUpdateMonitor, mLockPatternUtils, mSmartSpaceTransitionController); } @Test 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 5fb779adc5be..1aebf1c1c80d 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 @@ -127,4 +127,9 @@ public class FakeKeyguardStateController implements KeyguardStateController { public void notifyPanelFlingEnd() { } + + @Override + public boolean canPerformSmartSpaceTransition() { + return false; + } } |