OSDN Git Service

Don't make home stack visible if starting activity isn't translucent
authorWale Ogunwale <ogunwale@google.com>
Fri, 4 Mar 2016 18:27:32 +0000 (10:27 -0800)
committerWale Ogunwale <ogunwale@google.com>
Sun, 6 Mar 2016 03:18:30 +0000 (19:18 -0800)
We allow the home stack to be visible right behind the fullscreen
stack if all the activities fullscreen stack are translucent and
visible. However, if we are starting an acitvity it isn't visible
yet so our check for translucent activities in the fullscreen
stack will return true since there is nothing visible. This will
cause the home stack to the visible and the visiblilty of its app
token set to true in window manager and it been factored into the
transition animation.

In addition to checking if the activity is visible, we now also
check if it is the starting activity when trying to determine if
the stack is translucent.

Bug: 27448511
Change-Id: Icbbd57c0632cc5389c7ac894800a41f75d4bc450

services/core/java/com/android/server/am/ActivityMetricsLogger.java
services/core/java/com/android/server/am/ActivityStack.java
services/core/java/com/android/server/am/ActivityStarter.java

index 0e6dd28..43e1bdf 100644 (file)
@@ -61,7 +61,7 @@ class ActivityMetricsLogger {
         mLastLogTimeSecs = now;
 
         ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
-        if (stack != null && stack.getStackVisibilityLocked() != STACK_INVISIBLE) {
+        if (stack != null && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
             mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
             return;
         }
index d1e1d27..e50722a 100644 (file)
@@ -66,7 +66,6 @@ import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -1368,7 +1367,7 @@ final class ActivityStack {
             for (int i = stacks.size() - 1; i >= 0; --i) {
                 ActivityStack stack = stacks.get(i);
                 if (stack != this && stack.isFocusable()
-                        && stack.getStackVisibilityLocked() != STACK_INVISIBLE) {
+                        && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
                     return stack;
                 }
             }
@@ -1387,21 +1386,26 @@ final class ActivityStack {
         return false;
     }
 
-    private boolean hasTranslucentActivity(ActivityStack stack) {
-        final ArrayList<TaskRecord> tasks = stack.getAllTasks();
-        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            final TaskRecord task = tasks.get(taskNdx);
+    /**
+     * Returns true if the stack is translucent and can have other contents visible behind it if
+     * needed. A stack is considered translucent if it don't contain a visible or
+     * starting (about to be visible) activity that is fullscreen (opaque).
+     * @param starting The currently starting activity or null if there is none.
+     */
+    private boolean isStackTranslucent(ActivityRecord starting) {
+        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+            final TaskRecord task = mTaskHistory.get(taskNdx);
             final ArrayList<ActivityRecord> activities = task.mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = activities.get(activityNdx);
 
                 // Conditions for an activity to obscure the stack we're
                 // examining:
-                // 1. Not Finishing AND Visible AND:
+                // 1. Not Finishing AND (Visible or the Starting activity) AND:
                 // 2. Either:
                 // - Full Screen Activity OR
                 // - On top of Home and our stack is NOT home
-                if (!r.finishing && r.visible && (r.fullscreen ||
+                if (!r.finishing && (r.visible || r == starting) && (r.fullscreen ||
                         (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
                     return false;
                 }
@@ -1413,8 +1417,9 @@ final class ActivityStack {
     /**
      * Returns stack's visibility: {@link #STACK_INVISIBLE}, {@link #STACK_VISIBLE} or
      * {@link #STACK_VISIBLE_ACTIVITY_BEHIND}.
+     * @param starting The currently starting activity or null if there is none.
      */
-    int getStackVisibilityLocked() {
+    int getStackVisibilityLocked(ActivityRecord starting) {
         if (!isAttached()) {
             return STACK_INVISIBLE;
         }
@@ -1470,7 +1475,7 @@ final class ActivityStack {
         }
 
         if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
-                && hasTranslucentActivity(focusedStack)) {
+                && focusedStack.isStackTranslucent(starting)) {
             // Stacks behind the fullscreen stack with a translucent activity are always
             // visible so they can act as a backdrop to the translucent activity.
             // For example, dialog activities
@@ -1505,7 +1510,7 @@ final class ActivityStack {
                 return STACK_INVISIBLE;
             }
 
-            if (!hasTranslucentActivity(stack)) {
+            if (!stack.isStackTranslucent(starting)) {
                 return STACK_INVISIBLE;
             }
         }
@@ -1543,7 +1548,7 @@ final class ActivityStack {
         // If the top activity is not fullscreen, then we need to
         // make sure any activities under it are now visible.
         boolean aboveTop = top != null;
-        final int stackVisibility = getStackVisibilityLocked();
+        final int stackVisibility = getStackVisibilityLocked(starting);
         final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
         final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
         boolean behindFullscreenActivity = stackInvisible;
@@ -3806,7 +3811,8 @@ final class ActivityStack {
     void releaseBackgroundResources(ActivityRecord r) {
         if (hasVisibleBehindActivity() &&
                 !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
-            if (r == topRunningActivityLocked() && getStackVisibilityLocked() == STACK_VISIBLE) {
+            if (r == topRunningActivityLocked()
+                    && getStackVisibilityLocked(null) == STACK_VISIBLE) {
                 // Don't release the top activity if it has requested to run behind the next
                 // activity and the stack is currently visible.
                 return;
index 46389e2..83ad2a7 100644 (file)
@@ -1757,7 +1757,7 @@ class ActivityStarter {
             // and if yes, we will launch into that stack. If not, we just put the new
             // activity into parent's stack, because we can't find a better place.
             final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
-            if (stack != null && stack.getStackVisibilityLocked() == STACK_INVISIBLE) {
+            if (stack != null && stack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
                 // There is a docked stack, but it isn't visible, so we can't launch into that.
                 return null;
             } else {