Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfce4992 authored by Matt Pietal's avatar Matt Pietal Committed by Android (Google) Code Review
Browse files

Merge "Update user switching processes" into tm-dev

parents 4c97f3f5 c5b8459c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -147,6 +147,15 @@ public class KeyguardManager {
     */
    public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";

    /**
     * When switching to a secure user, system server will expect a callback when the UI has
     * completed the switch.
     *
     * @hide
     */
    public static final String LOCK_ON_USER_SWITCH_CALLBACK = "onSwitchCallback";


    /**
     *
     * Password lock type, see {@link #setLock}
+49 −18
Original line number Diff line number Diff line
@@ -138,8 +138,7 @@ const val UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L
class KeyguardUnlockAnimationController @Inject constructor(
    private val context: Context,
    private val keyguardStateController: KeyguardStateController,
    private val
    keyguardViewMediator: Lazy<KeyguardViewMediator>,
    private val keyguardViewMediator: Lazy<KeyguardViewMediator>,
    private val keyguardViewController: KeyguardViewController,
    private val featureFlags: FeatureFlags,
    private val biometricUnlockControllerLazy: Lazy<BiometricUnlockController>,
@@ -198,6 +197,12 @@ class KeyguardUnlockAnimationController @Inject constructor(
     */
    var playingCannedUnlockAnimation = false

    /**
     * Whether we reached the swipe gesture threshold to dismiss keyguard, or restore it, once and
     * should ignore any future changes to the dismiss amount before the animation finishes.
     */
    var dismissAmountThresholdsReached = false

    /**
     * Remote callback provided by Launcher that allows us to control the Launcher's unlock
     * animation and smartspace.
@@ -326,7 +331,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    playingCannedUnlockAnimation = false
                    keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
                    keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
                        false /* cancelled */
                    )
                }
@@ -516,7 +521,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
            // around behind that.
            biometricUnlockControllerLazy.get().isWakeAndUnlock -> {
                setSurfaceBehindAppearAmount(1f)
                keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
                keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
                    false /* cancelled */)
            }

@@ -553,7 +558,7 @@ class KeyguardUnlockAnimationController @Inject constructor(
                return@postDelayed
            }

            keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(
            keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
                false /* cancelled */)
        }, CANNED_UNLOCK_START_DELAY)
    }
@@ -625,6 +630,10 @@ class KeyguardUnlockAnimationController @Inject constructor(
            return
        }

        if (dismissAmountThresholdsReached) {
            return
        }

        if (!keyguardStateController.isShowing) {
            return
        }
@@ -657,6 +666,11 @@ class KeyguardUnlockAnimationController @Inject constructor(
            return
        }

        // no-op if we alreaddy reached a threshold.
        if (dismissAmountThresholdsReached) {
            return
        }

        // no-op if animation is not requested yet.
        if (!keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard() ||
                !keyguardViewMediator.get().isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe) {
@@ -671,7 +685,9 @@ class KeyguardUnlockAnimationController @Inject constructor(
                        !keyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture &&
                        dismissAmount >= DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD)) {
            setSurfaceBehindAppearAmount(1f)
            keyguardViewMediator.get().onKeyguardExitRemoteAnimationFinished(false /* cancelled */)
            dismissAmountThresholdsReached = true
            keyguardViewMediator.get().exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
                    false /* cancelled */)
        }
    }

@@ -726,28 +742,43 @@ class KeyguardUnlockAnimationController @Inject constructor(
     * This is generally triggered by us, calling
     * [KeyguardViewMediator.finishSurfaceBehindRemoteAnimation].
     */
    fun notifyFinishedKeyguardExitAnimation(cancelled: Boolean) {
    fun notifyFinishedKeyguardExitAnimation(showKeyguard: 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. If the launcher is doing its own animation, let it continue without
        // forcing it to 1f.
        // The lockscreen surface is gone, so it is now safe to re-show the smartspace.
        if (lockscreenSmartspace?.visibility == View.INVISIBLE) {
            lockscreenSmartspace?.visibility = View.VISIBLE
        }

        if (!showKeyguard) {
            // Make sure we made the surface behind fully visible, just in case. It should already
            // be fully visible. The exit animation is finished, and we should not hold the leash
            // anymore, so forcing it to 1f.
            surfaceBehindAlpha = 1f
            setSurfaceBehindAppearAmount(1f)

            try {
                launcherUnlockController?.setUnlockAmount(1f, false /* forceIfAnimating */)
            } catch (e: RemoteException) {
                Log.e(TAG, "Remote exception in notifyFinishedKeyguardExitAnimation", e)
            }
        }

        listeners.forEach { it.onUnlockAnimationFinished() }

        // Reset all state
        surfaceBehindAlphaAnimator.cancel()
        surfaceBehindEntryAnimator.cancel()

        // That target is no longer valid since the animation finished, null it out.
        surfaceBehindRemoteAnimationTarget = null
        surfaceBehindParams = null

        playingCannedUnlockAnimation = false
        dismissAmountThresholdsReached = false
        willUnlockWithInWindowLauncherAnimations = false
        willUnlockWithSmartspaceTransition = false

        // The lockscreen surface is gone, so it is now safe to re-show the smartspace.
        lockscreenSmartspace?.visibility = View.VISIBLE

        listeners.forEach { it.onUnlockAnimationFinished() }
    }

    /**
+279 −79

File changed.

Preview size limit exceeded, changes collapsed.

+3 −3
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {

        // Also expect we've immediately asked the keyguard view mediator to finish the remote
        // animation.
        verify(keyguardViewMediator, times(1)).onKeyguardExitRemoteAnimationFinished(
        verify(keyguardViewMediator, times(1)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
            false /* cancelled */)

        verifyNoMoreInteractions(surfaceTransactionApplier)
@@ -136,7 +136,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() {
        )

        // Since the animation is running, we should not have finished the remote animation.
        verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished(
        verify(keyguardViewMediator, times(0)).exitKeyguardAndFinishSurfaceBehindRemoteAnimation(
            false /* cancelled */)
    }

+25 −30
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
import static android.app.ActivityManagerInternal.ALLOW_PROFILES_OR_NON_FULL;
import static android.app.KeyguardManager.LOCK_ON_USER_SWITCH_CALLBACK;
import static android.os.PowerWhitelistManager.REASON_BOOT_COMPLETED;
import static android.os.PowerWhitelistManager.REASON_LOCKED_BOOT_COMPLETED;
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
@@ -103,7 +104,6 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils;
@@ -127,6 +127,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
@@ -1580,7 +1582,8 @@ class UserController implements Handler.Callback {
                    mInjector.getWindowManager().setSwitchingUser(true);
                    // Only lock if the user has a secure keyguard PIN/Pattern/Pwd
                    if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
                        mInjector.getWindowManager().lockNow(null);
                        // Make sure the device is locked before moving on with the user switch
                        mInjector.lockDeviceNowAndWaitForKeyguardShown();
                    }
                }
            } else {
@@ -2039,22 +2042,9 @@ class UserController implements Handler.Callback {
    @VisibleForTesting
    void completeUserSwitch(int newUserId) {
        if (isUserSwitchUiEnabled()) {
            // If there is no challenge set, dismiss the keyguard right away
            if (!mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
                // Wait until the keyguard is dismissed to unfreeze
                mInjector.dismissKeyguard(
                        new Runnable() {
                            public void run() {
                                unfreezeScreen();
                            }
                        },
                        "User Switch");
                return;
            } else {
            unfreezeScreen();
        }
    }
    }

    /**
     * Tell WindowManager we're ready to unfreeze the screen, at its leisure. Note that there is
@@ -3381,23 +3371,28 @@ class UserController implements Handler.Callback {
            return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
        }

        protected void dismissKeyguard(Runnable runnable, String reason) {
            getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() {
                @Override
                public void onDismissError() throws RemoteException {
                    mHandler.post(runnable);
                }
        void lockDeviceNowAndWaitForKeyguardShown() {
            final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
            t.traceBegin("lockDeviceNowAndWaitForKeyguardShown");

                @Override
                public void onDismissSucceeded() throws RemoteException {
                    mHandler.post(runnable);
            final CountDownLatch latch = new CountDownLatch(1);
            Bundle bundle = new Bundle();
            bundle.putBinder(LOCK_ON_USER_SWITCH_CALLBACK, new IRemoteCallback.Stub() {
                public void sendResult(Bundle data) {
                    latch.countDown();
                }

                @Override
                public void onDismissCancelled() throws RemoteException {
                    mHandler.post(runnable);
            });
            getWindowManager().lockNow(bundle);
            try {
                if (!latch.await(20, TimeUnit.SECONDS)) {
                    throw new RuntimeException("User controller expected a callback while waiting "
                            + "to show the keyguard. Timed out after 20 seconds.");
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                t.traceEnd();
            }
            }, reason);
        }
    }
}
Loading