Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.server.wm; |
| 18 | |
| 19 | import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; |
| 20 | |
| 21 | import static com.android.server.wm.ActivityStack.TAG_VISIBILITY; |
| 22 | import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; |
| 23 | |
Diego Vela | 671c007 | 2020-03-25 09:39:26 -0700 | [diff] [blame] | 24 | import android.annotation.Nullable; |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 25 | import android.util.Slog; |
| 26 | |
| 27 | import com.android.internal.util.function.pooled.PooledConsumer; |
| 28 | import com.android.internal.util.function.pooled.PooledLambda; |
| 29 | |
| 30 | /** Helper class to ensure activities are in the right visible state for a container. */ |
| 31 | class EnsureActivitiesVisibleHelper { |
| 32 | private final ActivityStack mContiner; |
| 33 | private ActivityRecord mTop; |
| 34 | private ActivityRecord mStarting; |
| 35 | private boolean mAboveTop; |
| 36 | private boolean mContainerShouldBeVisible; |
| 37 | private boolean mBehindFullscreenActivity; |
| 38 | private int mConfigChanges; |
| 39 | private boolean mPreserveWindows; |
| 40 | private boolean mNotifyClients; |
| 41 | |
| 42 | EnsureActivitiesVisibleHelper(ActivityStack container) { |
| 43 | mContiner = container; |
| 44 | } |
| 45 | |
Diego Vela | 671c007 | 2020-03-25 09:39:26 -0700 | [diff] [blame] | 46 | /** |
| 47 | * Update all attributes except {@link mContiner} to use in subsequent calculations. |
| 48 | * |
| 49 | * @param starting The activity that is being started |
| 50 | * @param configChanges Parts of the configuration that changed for this activity for evaluating |
| 51 | * if the screen should be frozen. |
| 52 | * @param preserveWindows Flag indicating whether windows should be preserved when updating. |
| 53 | * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc |
| 54 | * be sent to the clients. |
| 55 | */ |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 56 | void reset(ActivityRecord starting, int configChanges, boolean preserveWindows, |
| 57 | boolean notifyClients) { |
| 58 | mStarting = starting; |
Wale Ogunwale | 85fb19a | 2019-12-05 10:41:05 +0900 | [diff] [blame] | 59 | mTop = mContiner.topRunningActivity(); |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 60 | // If the top activity is not fullscreen, then we need to make sure any activities under it |
| 61 | // are now visible. |
| 62 | mAboveTop = mTop != null; |
| 63 | mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting); |
| 64 | mBehindFullscreenActivity = !mContainerShouldBeVisible; |
| 65 | mConfigChanges = configChanges; |
| 66 | mPreserveWindows = preserveWindows; |
| 67 | mNotifyClients = notifyClients; |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Ensure visibility with an option to also update the configuration of visible activities. |
| 72 | * @see ActivityStack#ensureActivitiesVisible(ActivityRecord, int, boolean) |
Louis Chang | 149d5c8 | 2019-12-30 09:47:39 +0800 | [diff] [blame] | 73 | * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) |
Diego Vela | 671c007 | 2020-03-25 09:39:26 -0700 | [diff] [blame] | 74 | * @param starting The top most activity in the task. |
| 75 | * The activity is either starting or resuming. |
| 76 | * Caller should ensure starting activity is visible. |
| 77 | * |
| 78 | * @param configChanges Parts of the configuration that changed for this activity for evaluating |
| 79 | * if the screen should be frozen. |
| 80 | * @param preserveWindows Flag indicating whether windows should be preserved when updating. |
| 81 | * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc |
| 82 | * be sent to the clients. |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 83 | */ |
Diego Vela | 671c007 | 2020-03-25 09:39:26 -0700 | [diff] [blame] | 84 | void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows, |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 85 | boolean notifyClients) { |
| 86 | reset(starting, configChanges, preserveWindows, notifyClients); |
| 87 | |
| 88 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop |
| 89 | + " configChanges=0x" + Integer.toHexString(configChanges)); |
| 90 | if (mTop != null) { |
| 91 | mContiner.checkTranslucentActivityWaiting(mTop); |
| 92 | } |
| 93 | |
| 94 | // We should not resume activities that being launched behind because these |
| 95 | // activities are actually behind other fullscreen activities, but still required |
| 96 | // to be visible (such as performing Recents animation). |
| 97 | final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind |
Evan Rosky | 226de13 | 2020-01-03 18:00:29 -0800 | [diff] [blame] | 98 | && mContiner.isTopActivityFocusable() |
Wale Ogunwale | 0d46519 | 2020-01-23 19:14:44 -0800 | [diff] [blame] | 99 | && (starting == null || !starting.isDescendantOf(mContiner)); |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 100 | |
| 101 | final PooledConsumer f = PooledLambda.obtainConsumer( |
| 102 | EnsureActivitiesVisibleHelper::setActivityVisibilityState, this, |
Andrii Kulian | b9faa03 | 2019-10-17 23:11:54 -0700 | [diff] [blame] | 103 | PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity); |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 104 | mContiner.forAllActivities(f); |
| 105 | f.recycle(); |
| 106 | } |
| 107 | |
Andrii Kulian | b9faa03 | 2019-10-17 23:11:54 -0700 | [diff] [blame] | 108 | private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting, |
| 109 | final boolean resumeTopActivity) { |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 110 | final boolean isTop = r == mTop; |
| 111 | if (mAboveTop && !isTop) { |
| 112 | return; |
| 113 | } |
| 114 | mAboveTop = false; |
| 115 | |
| 116 | final boolean reallyVisible = r.shouldBeVisible( |
| 117 | mBehindFullscreenActivity, false /* ignoringKeyguard */); |
| 118 | |
| 119 | // Check whether activity should be visible without Keyguard influence |
| 120 | if (r.visibleIgnoringKeyguard) { |
| 121 | if (r.occludesParent()) { |
| 122 | // At this point, nothing else needs to be shown in this task. |
| 123 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r |
| 124 | + " stackVisible=" + mContainerShouldBeVisible |
| 125 | + " behindFullscreen=" + mBehindFullscreenActivity); |
| 126 | mBehindFullscreenActivity = true; |
| 127 | } else { |
| 128 | mBehindFullscreenActivity = false; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | if (reallyVisible) { |
| 133 | if (r.finishing) { |
| 134 | return; |
| 135 | } |
| 136 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r |
| 137 | + " finishing=" + r.finishing + " state=" + r.getState()); |
| 138 | // First: if this is not the current activity being started, make |
| 139 | // sure it matches the current configuration. |
| 140 | if (r != mStarting && mNotifyClients) { |
| 141 | r.ensureActivityConfiguration(0 /* globalChanges */, mPreserveWindows, |
| 142 | true /* ignoreVisibility */); |
| 143 | } |
| 144 | |
| 145 | if (!r.attachedToProcess()) { |
| 146 | makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop, |
| 147 | resumeTopActivity && isTop, r); |
| 148 | } else if (r.mVisibleRequested) { |
| 149 | // If this activity is already visible, then there is nothing to do here. |
| 150 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, |
| 151 | "Skipping: already visible at " + r); |
| 152 | |
| 153 | if (r.mClientVisibilityDeferred && mNotifyClients) { |
Andrii Kulian | b9faa03 | 2019-10-17 23:11:54 -0700 | [diff] [blame] | 154 | r.makeActiveIfNeeded(r.mClientVisibilityDeferred ? null : starting); |
| 155 | r.mClientVisibilityDeferred = false; |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | r.handleAlreadyVisible(); |
| 159 | if (mNotifyClients) { |
| 160 | r.makeActiveIfNeeded(mStarting); |
| 161 | } |
| 162 | } else { |
| 163 | r.makeVisibleIfNeeded(mStarting, mNotifyClients); |
| 164 | } |
| 165 | // Aggregate current change flags. |
| 166 | mConfigChanges |= r.configChangeFlags; |
| 167 | } else { |
| 168 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r |
| 169 | + " finishing=" + r.finishing + " state=" + r.getState() |
| 170 | + " stackShouldBeVisible=" + mContainerShouldBeVisible |
| 171 | + " behindFullscreenActivity=" + mBehindFullscreenActivity |
| 172 | + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); |
| 173 | r.makeInvisible(); |
| 174 | } |
| 175 | |
| 176 | final int windowingMode = mContiner.getWindowingMode(); |
| 177 | if (windowingMode == WINDOWING_MODE_FREEFORM) { |
| 178 | // The visibility of tasks and the activities they contain in freeform stack are |
| 179 | // determined individually unlike other stacks where the visibility or fullscreen |
| 180 | // status of an activity in a previous task affects other. |
| 181 | mBehindFullscreenActivity = !mContainerShouldBeVisible; |
Jeff Chang | 24b0bf6 | 2019-12-19 19:15:07 +0800 | [diff] [blame] | 182 | } else if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome() |
| 183 | && r.isRootOfTask()) { |
Wale Ogunwale | 076c3b1 | 2019-11-20 12:17:22 -0800 | [diff] [blame] | 184 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner |
| 185 | + " stackShouldBeVisible=" + mContainerShouldBeVisible |
| 186 | + " behindFullscreenActivity=" + mBehindFullscreenActivity); |
| 187 | // No other task in the home stack should be visible behind the home activity. |
| 188 | // Home activities is usually a translucent activity with the wallpaper behind |
| 189 | // them. However, when they don't have the wallpaper behind them, we want to |
| 190 | // show activities in the next application stack behind them vs. another |
| 191 | // task in the home stack like recents. |
| 192 | mBehindFullscreenActivity = true; |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, |
| 197 | boolean isTop, boolean andResume, ActivityRecord r) { |
| 198 | // We need to make sure the app is running if it's the top, or it is just made visible from |
| 199 | // invisible. If the app is already visible, it must have died while it was visible. In this |
| 200 | // case, we'll show the dead window but will not restart the app. Otherwise we could end up |
| 201 | // thrashing. |
| 202 | if (!isTop && r.mVisibleRequested) { |
| 203 | return; |
| 204 | } |
| 205 | |
| 206 | // This activity needs to be visible, but isn't even running... |
| 207 | // get it started and resume if no other stack in this stack is resumed. |
| 208 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r); |
| 209 | if (r != starting) { |
| 210 | r.startFreezingScreenLocked(configChanges); |
| 211 | } |
| 212 | if (!r.mVisibleRequested || r.mLaunchTaskBehind) { |
| 213 | if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r); |
| 214 | r.setVisibility(true); |
| 215 | } |
| 216 | if (r != starting) { |
| 217 | mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */); |
| 218 | } |
| 219 | } |
| 220 | } |