Exit dream within keyguard-going-away transition
This ensures that the dream will exit immediately and not be visible
after unlocking the device, by bundling the dream exit transition with
the keyguard unlock transition.
Bug: 333829441
Test: unlocked by swiping open bouncer on dream and using fingerprint
unlock
Flag: ACONFIG android.service.dreams.dismiss_dream_on_keyguard_dismiss
DISABLED
Change-Id: Ie4587704bcc23794ba841077e34b9c4a1ee1c3e7
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
index f87cb85..a42eaff 100644
--- a/core/java/android/service/dreams/flags.aconfig
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -29,6 +29,16 @@
}
flag {
+ name: "dismiss_dream_on_keyguard_dismiss"
+ namespace: "systemui"
+ description: "Dismisses the dream in the keyguard-going-away transition, preventing it from being visible"
+ bug: "333829441"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "dream_tracks_focus"
namespace: "communal"
description: "This flag enables the ability for dreams to track whether or not they have focus"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 6834e6d..17121c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -702,10 +702,12 @@
ShellInit shellInit,
ShellController shellController,
Transitions transitions,
+ TaskStackListenerImpl taskStackListener,
@ShellMainThread Handler mainHandler,
@ShellMainThread ShellExecutor mainExecutor) {
return new KeyguardTransitionHandler(
- shellInit, shellController, transitions, mainHandler, mainExecutor);
+ shellInit, shellController, transitions, taskStackListener, mainHandler,
+ mainExecutor);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index 863a51a..9eaf7e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -44,10 +45,13 @@
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerCallback;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.annotations.ExternalThread;
import com.android.wm.shell.sysui.KeyguardChangeListener;
@@ -62,7 +66,8 @@
* <p>This takes the highest priority.
*/
public class KeyguardTransitionHandler
- implements Transitions.TransitionHandler, KeyguardChangeListener {
+ implements Transitions.TransitionHandler, KeyguardChangeListener,
+ TaskStackListenerCallback {
private static final String TAG = "KeyguardTransition";
private final Transitions mTransitions;
@@ -71,6 +76,7 @@
private final ShellExecutor mMainExecutor;
private final ArrayMap<IBinder, StartedTransition> mStartedTransitions = new ArrayMap<>();
+ private final TaskStackListenerImpl mTaskStackListener;
/**
* Local IRemoteTransition implementations registered by the keyguard service.
@@ -87,6 +93,8 @@
// Last value reported by {@link KeyguardChangeListener}.
private boolean mKeyguardShowing = true;
+ @Nullable
+ private WindowContainerToken mDreamToken;
private final class StartedTransition {
final TransitionInfo mInfo;
@@ -105,18 +113,23 @@
@NonNull ShellInit shellInit,
@NonNull ShellController shellController,
@NonNull Transitions transitions,
+ @NonNull TaskStackListenerImpl taskStackListener,
@NonNull Handler mainHandler,
@NonNull ShellExecutor mainExecutor) {
mTransitions = transitions;
mShellController = shellController;
mMainHandler = mainHandler;
mMainExecutor = mainExecutor;
+ mTaskStackListener = taskStackListener;
shellInit.addInitCallback(this::onInit, this);
}
private void onInit() {
mTransitions.addHandler(this);
mShellController.addKeyguardChangeListener(this);
+ if (dismissDreamOnKeyguardDismiss()) {
+ mTaskStackListener.addListener(this);
+ }
}
/**
@@ -142,6 +155,11 @@
}
@Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+ mDreamToken = taskInfo.getActivityType() == ACTIVITY_TYPE_DREAM ? taskInfo.token : null;
+ }
+
+ @Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@@ -271,6 +289,13 @@
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
+ if (dismissDreamOnKeyguardDismiss()
+ && (request.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0
+ && mDreamToken != null) {
+ // Dismiss the dream in the same transaction, so that it isn't visible once the device
+ // is unlocked.
+ return new WindowContainerTransaction().removeTask(mDreamToken);
+ }
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index ae163ea..674c128 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -89,14 +90,14 @@
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.transition.Transitions;
-import kotlinx.coroutines.CoroutineScope;
-
import java.util.ArrayList;
import java.util.Map;
import java.util.WeakHashMap;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineScope;
+
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
@@ -223,6 +224,20 @@
initAlphaForAnimationTargets(t, apps);
initAlphaForAnimationTargets(t, wallpapers);
+ // If the keyguard is going away, hide the dream if one exists.
+ if (dismissDreamOnKeyguardDismiss()
+ && (info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
+ for (RemoteAnimationTarget app : apps) {
+ final boolean isDream = app.taskInfo != null
+ && app.taskInfo.getActivityType()
+ == WindowConfiguration.ACTIVITY_TYPE_DREAM;
+ if (isDream && app.mode == RemoteAnimationTarget.MODE_CLOSING) {
+ t.hide(app.leash);
+ break;
+ }
+ }
+ }
+
t.apply();
runner.onAnimationStart(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 46aec25..5d31d1e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -21,6 +21,7 @@
import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
@@ -3092,13 +3093,22 @@
createInteractionJankMonitorConf(
CUJ_LOCKSCREEN_UNLOCK_ANIMATION, "DismissPanel"));
+ // Filter out any closing apps, such as the dream.
+ RemoteAnimationTarget[] openingApps = apps;
+ if (dismissDreamOnKeyguardDismiss()) {
+ openingApps = Arrays.stream(apps)
+ .filter(a -> a.mode == RemoteAnimationTarget.MODE_OPENING)
+ .toArray(RemoteAnimationTarget[]::new);
+ }
+
// Pass the surface and metadata to the unlock animation controller.
RemoteAnimationTarget[] openingWallpapers = Arrays.stream(wallpapers).filter(
w -> w.mode == RemoteAnimationTarget.MODE_OPENING).toArray(
RemoteAnimationTarget[]::new);
+
mKeyguardUnlockAnimationControllerLazy.get()
.notifyStartSurfaceBehindRemoteAnimation(
- apps, openingWallpapers, startTime,
+ openingApps, openingWallpapers, startTime,
mSurfaceBehindRemoteAnimationRequested);
} else {
mInteractionJankMonitor.begin(