From 936aaeb8781e55e988578e7c8b19e973a37b50f1 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Fri, 26 Aug 2016 19:02:11 -0700 Subject: [PATCH] Fix bug that apps are not unminimizing if recent tasks are empty If an activity was launched in the docked stack and we weren't able to retrace the launch back to an activity launch from the homescreen in activity manager, nothing happened. Now we try to do a better job by also checking some conditions when the app transition is starting. Note that this might still be racy, but in practice all activities are usually launched from the same process so the app is done starting/finishing any activities when the first frame is drawn, so we are able to catch the correct state when we figure out that the app transition is starting. In addition to that, we also need to not hide the docked stack while lockscreen is showing. This doesn't make any sense anymore as we are dismissing the docked stack when we show something above the lockscreen, and this only lead to issues that triggered app visibility events which triggered this special unnecessarily. This also fixes some flicker/ race-condition in the normal unlocking process I noticed a long time ago but couldn't really reproduce. Change-Id: I42683520ba9ee9fbd0c9920501387a573ac94655 Fixes: 30439313 --- .../com/android/server/am/ActivityStack.java | 5 ---- .../android/server/am/ActivityStarter.java | 3 +++ .../com/android/server/wm/AppTransition.java | 2 +- .../wm/DockedStackDividerController.java | 26 ++++++++++++++++++- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index a27adf7fcf161..02c227e54b2c5 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1591,11 +1591,6 @@ final class ActivityStack { return STACK_INVISIBLE; } - final boolean isLockscreenShown = mService.mLockScreenShown == LOCK_SCREEN_SHOWN; - if (isLockscreenShown && !StackId.isAllowedOverLockscreen(mStackId)) { - return STACK_INVISIBLE; - } - final ActivityStack focusedStack = mStackSupervisor.getFocusedStack(); final int focusedStackId = focusedStack.mStackId; diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 5252446990825..3083df671b29b 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -572,6 +572,9 @@ class ActivityStarter { // If we launched the activity from a no display activity that was launched from the home // screen, we also need to start recents to un-minimize the docked stack, since the // noDisplay activity will be finished shortly after. + // Note that some apps have trampoline activities without noDisplay being set. In that case, + // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting + // that tries to detect that case. // TODO: We should prevent noDisplay activities from affecting task/stack ordering and // visibility instead of using this flag. final boolean noDisplayActivityOverHome = sourceRecord != null diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index d4d6f3225edd3..e4ec295fa34e5 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -382,7 +382,7 @@ public class AppTransition implements Dump { topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null, topClosingAppAnimator != null ? topClosingAppAnimator.animation : null); mService.getDefaultDisplayContentLocked().getDockedDividerController() - .notifyAppTransitionStarting(); + .notifyAppTransitionStarting(openingApps); // Prolong the start for the transition when docking a task from recents, unless recents // ended it already then we don't need to wait. diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index f93e2ffa73bee..f8d2ee931d047 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -38,6 +38,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.util.ArraySet; import android.util.Slog; import android.view.DisplayInfo; import android.view.IDockedStackListener; @@ -492,8 +493,31 @@ public class DockedStackDividerController implements DimLayerUser { checkMinimizeChanged(false /* animate */); } - void notifyAppTransitionStarting() { + void notifyAppTransitionStarting(ArraySet openingApps) { + final boolean wasMinimized = mMinimizedDock; checkMinimizeChanged(true /* animate */); + + // We were minimized, and now we are still minimized, but somebody is trying to launch an + // app in docked stack, better show recent apps so we actually get unminimized! This catches + // any case that was missed in ActivityStarter.postStartActivityUncheckedProcessing because + // we couldn't retrace the launch of the app in the docked stack to the launch from + // homescreen. + if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps)) { + mService.showRecentApps(true /* fromHome */); + } + } + + /** + * @return true if {@param apps} contains an activity in the docked stack, false otherwise. + */ + private boolean containsAppInDockedStack(ArraySet apps) { + for (int i = apps.size() - 1; i >= 0; i--) { + final AppWindowToken token = apps.valueAt(i); + if (token.mTask != null && token.mTask.mStack.mStackId == DOCKED_STACK_ID) { + return true; + } + } + return false; } boolean isMinimizedDock() {