OSDN Git Service

Fix transition between two occluding activities
authorJorim Jaggi <jjaggi@google.com>
Mon, 28 Aug 2017 13:44:43 +0000 (15:44 +0200)
committerJorim Jaggi <jjaggi@google.com>
Mon, 28 Aug 2017 13:52:38 +0000 (15:52 +0200)
This fixes an issue when starting an activity that occldues
Keyguard with the window flag from an activity that is already
occluding Keyguard. Normally we wait until the transition starts
until the next activity had a chance to set its layout flag
(FLAG_SHOW_WHEN_LOCKED) with the UnknownVisibilityController.

Now, since setAppVisibility(false) was called after immediately
starting the activity, we removed the activity immediately from
the UnknownVisibilityController waiting list and then unoccluded
Keyguard.

We fix this by only removing the activity from the waiting list if
the app is actually hidden and not just because it's hidden by
Keyguard.

This regressed from I745e985766a1af97203e1d22b6443dabdd0c0363
because calling setVisible(true) was setting the token's visible
to true. Then, setVisible(false) was NOT ignored anymore.
Previously it was just ignored because the app wasn't made visible
yet from WM perspective.

Test: go/wm-smoke
Test: android.server.cts.KeyguardTransitionTests#testNewActivityDuringOccluded
Test: Launch camera from Keyguard with animation transition scale
set to 0. (regression test)

Change-Id: I36ec1bf335c48baf298e78620381bdd0be34aa1d
Fixes: 65061212
Bug: 37677242

services/core/java/com/android/server/am/ActivityRecord.java
services/core/java/com/android/server/am/ActivityStackSupervisor.java
services/core/java/com/android/server/wm/AppWindowContainerController.java

index 874bd1e..c49ea81 100644 (file)
@@ -1572,7 +1572,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
     }
 
     void setVisibility(boolean visible) {
-        mWindowContainerController.setVisibility(visible, mDeferHidingClient);
+        mWindowContainerController.setVisibility(visible, visibleIgnoringKeyguard,
+                mDeferHidingClient);
         mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this, visible);
     }
 
index 68a4ad9..4cc2892 100644 (file)
@@ -1336,6 +1336,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
 
             r.app = app;
 
+            if (mKeyguardController.isKeyguardLocked()) {
+                r.notifyUnknownVisibilityLaunched();
+            }
+
             // Have the window manager re-evaluate the orientation of the screen based on the new
             // activity order.  Note that as a result of this, it can call back into the activity
             // manager with a new orientation.  We don't care about that, because the activity is
@@ -1362,9 +1366,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                 r.setVisibility(true);
             }
 
-            if (mKeyguardController.isKeyguardLocked()) {
-                r.notifyUnknownVisibilityLaunched();
-            }
             final int applicationInfoUid =
                     (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
             if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
index f142ff6..ebd82e3 100644 (file)
@@ -321,7 +321,8 @@ public class AppWindowContainerController
         }
     }
 
-    public void setVisibility(boolean visible, boolean deferHidingClient) {
+    public void setVisibility(boolean visible, boolean visibleIgnoringKeyguard,
+            boolean deferHidingClient) {
         synchronized(mWindowMap) {
             if (mContainer == null) {
                 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
@@ -360,13 +361,16 @@ public class AppWindowContainerController
             wtoken.hiddenRequested = !visible;
             wtoken.mDeferHidingClient = deferHidingClient;
 
+            if (!visibleIgnoringKeyguard) {
+                mService.mUnknownAppVisibilityController.appRemovedOrHidden(wtoken);
+            }
+
             if (!visible) {
                 // If the app is dead while it was visible, we kept its dead window on screen.
                 // Now that the app is going invisible, we can remove it. It will be restarted
                 // if made visible again.
                 wtoken.removeDeadWindows();
                 wtoken.setVisibleBeforeClientHidden();
-                mService.mUnknownAppVisibilityController.appRemovedOrHidden(wtoken);
             } else {
                 if (!mService.mAppTransition.isTransitionSet()
                         && mService.mAppTransition.isReady()) {