From 8051c5c89060906f5a3a1ca4adb3b53bb423e56b Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Fri, 4 Mar 2016 10:27:32 -0800 Subject: [PATCH] Don't make home stack visible if starting activity isn't translucent 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 --- .../server/am/ActivityMetricsLogger.java | 2 +- .../com/android/server/am/ActivityStack.java | 32 +++++++++++-------- .../android/server/am/ActivityStarter.java | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 0e6dd28379b32..43e1bdfb5e97e 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -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; } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index d1e1d27af1f69..e50722ac04d84 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -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 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 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; diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 46389e2ef803e..83ad2a7ebfdd8 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -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 {