Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [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 | |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 19 | import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; |
| 20 | import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 21 | import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; |
| 22 | import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; |
Tarandeep Singh | b9538cd | 2020-02-20 17:51:18 -0800 | [diff] [blame] | 23 | import static android.view.InsetsController.ANIMATION_TYPE_HIDE; |
| 24 | import static android.view.InsetsController.ANIMATION_TYPE_SHOW; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 25 | import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; |
| 26 | import static android.view.InsetsState.ITYPE_STATUS_BAR; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 27 | import static android.view.SyncRtSurfaceTransactionApplier.applyParams; |
wilsonshih | e832194 | 2019-10-18 18:39:46 +0800 | [diff] [blame] | 28 | import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 29 | import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; |
| 30 | |
| 31 | import android.annotation.Nullable; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 32 | import android.app.StatusBarManager; |
| 33 | import android.util.IntArray; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 34 | import android.util.SparseArray; |
| 35 | import android.view.InsetsAnimationControlCallbacks; |
| 36 | import android.view.InsetsAnimationControlImpl; |
Jorim Jaggi | 6d5c801 | 2020-02-28 01:40:27 +0100 | [diff] [blame] | 37 | import android.view.InsetsAnimationControlRunner; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 38 | import android.view.InsetsController; |
| 39 | import android.view.InsetsSourceControl; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 40 | import android.view.InsetsState; |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 41 | import android.view.InsetsState.InternalInsetsType; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 42 | import android.view.SurfaceControl; |
| 43 | import android.view.SyncRtSurfaceTransactionApplier; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 44 | import android.view.ViewRootImpl; |
Adrian Roos | db5b0c2 | 2020-02-12 15:05:27 -0800 | [diff] [blame] | 45 | import android.view.WindowInsetsAnimation; |
Jorim Jaggi | 6d5c801 | 2020-02-28 01:40:27 +0100 | [diff] [blame] | 46 | import android.view.WindowInsetsAnimation.Bounds; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 47 | import android.view.WindowInsetsAnimationControlListener; |
| 48 | |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 49 | import com.android.internal.annotations.VisibleForTesting; |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 50 | import com.android.server.DisplayThread; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 51 | |
| 52 | /** |
| 53 | * Policy that implements who gets control over the windows generating insets. |
| 54 | */ |
| 55 | class InsetsPolicy { |
| 56 | |
| 57 | private final InsetsStateController mStateController; |
| 58 | private final DisplayContent mDisplayContent; |
| 59 | private final DisplayPolicy mPolicy; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 60 | private final IntArray mShowingTransientTypes = new IntArray(); |
| 61 | |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 62 | /** For resetting visibilities of insets sources. */ |
| 63 | private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { }; |
| 64 | |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 65 | private WindowState mFocusedWin; |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 66 | private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 67 | private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 68 | private boolean mAnimatingShown; |
| 69 | private final float[] mTmpFloat9 = new float[9]; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 70 | |
| 71 | InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) { |
| 72 | mStateController = stateController; |
| 73 | mDisplayContent = displayContent; |
| 74 | mPolicy = displayContent.getDisplayPolicy(); |
| 75 | } |
| 76 | |
| 77 | /** Updates the target which can control system bars. */ |
| 78 | void updateBarControlTarget(@Nullable WindowState focusedWin) { |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 79 | if (mFocusedWin != focusedWin){ |
| 80 | abortTransient(); |
| 81 | } |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 82 | mFocusedWin = focusedWin; |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 83 | mStateController.onBarControlTargetChanged(getStatusControlTarget(focusedWin), |
| 84 | getFakeStatusControlTarget(focusedWin), |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 85 | getNavControlTarget(focusedWin), |
| 86 | getFakeNavControlTarget(focusedWin)); |
| 87 | if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { |
| 88 | return; |
| 89 | } |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 90 | mStatusBar.setVisible(focusedWin == null |
| 91 | || focusedWin != getStatusControlTarget(focusedWin) |
Jorim Jaggi | 0dd0cf9 | 2019-12-27 15:17:44 +0100 | [diff] [blame] | 92 | || focusedWin.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).isVisible()); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 93 | mNavBar.setVisible(focusedWin == null |
| 94 | || focusedWin != getNavControlTarget(focusedWin) |
Jorim Jaggi | 0dd0cf9 | 2019-12-27 15:17:44 +0100 | [diff] [blame] | 95 | || focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR) |
| 96 | .isVisible()); |
Tiger Huang | 9ff42bd | 2020-05-01 03:27:33 +0800 | [diff] [blame] | 97 | mPolicy.updateHideNavInputEventReceiver(); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 98 | } |
| 99 | |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 100 | boolean isHidden(@InternalInsetsType int type) { |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 101 | final InsetsSourceProvider provider = mStateController.peekSourceProvider(type); |
| 102 | return provider != null && provider.hasWindow() && !provider.getSource().isVisible(); |
| 103 | } |
| 104 | |
| 105 | void showTransient(IntArray types) { |
| 106 | boolean changed = false; |
| 107 | for (int i = types.size() - 1; i >= 0; i--) { |
| 108 | final int type = types.get(i); |
| 109 | if (mShowingTransientTypes.indexOf(type) != -1) { |
| 110 | continue; |
| 111 | } |
| 112 | if (!isHidden(type)) { |
| 113 | continue; |
| 114 | } |
| 115 | mShowingTransientTypes.add(type); |
| 116 | changed = true; |
| 117 | } |
| 118 | if (changed) { |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 119 | mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(), |
| 120 | mShowingTransientTypes.toArray()); |
| 121 | updateBarControlTarget(mFocusedWin); |
Tiger Huang | e480e5f | 2020-04-16 23:26:49 +0800 | [diff] [blame] | 122 | |
| 123 | // The leashes can be created while updating bar control target. The surface transaction |
| 124 | // of the new leashes might not be applied yet. The callback posted here ensures we can |
| 125 | // get the valid leashes because the surface transaction will be applied in the next |
| 126 | // animation frame which will be triggered if a new leash is created. |
| 127 | mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 128 | synchronized (mDisplayContent.mWmService.mGlobalLock) { |
Tiger Huang | e480e5f | 2020-04-16 23:26:49 +0800 | [diff] [blame] | 129 | final InsetsState state = new InsetsState(mStateController.getRawInsetsState()); |
| 130 | startAnimation(true /* show */, () -> { |
| 131 | synchronized (mDisplayContent.mWmService.mGlobalLock) { |
| 132 | mStateController.notifyInsetsChanged(); |
| 133 | } |
| 134 | }, state); |
| 135 | mStateController.onInsetsModified(mDummyControlTarget, state); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 136 | } |
Tiger Huang | e480e5f | 2020-04-16 23:26:49 +0800 | [diff] [blame] | 137 | }); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 138 | } |
| 139 | } |
| 140 | |
| 141 | void hideTransient() { |
| 142 | if (mShowingTransientTypes.size() == 0) { |
| 143 | return; |
| 144 | } |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 145 | InsetsState state = new InsetsState(mStateController.getRawInsetsState()); |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 146 | startAnimation(false /* show */, () -> { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 147 | synchronized (mDisplayContent.mWmService.mGlobalLock) { |
| 148 | mShowingTransientTypes.clear(); |
| 149 | mStateController.notifyInsetsChanged(); |
| 150 | updateBarControlTarget(mFocusedWin); |
| 151 | } |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 152 | }, state); |
| 153 | mStateController.onInsetsModified(mDummyControlTarget, state); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 154 | } |
| 155 | |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 156 | boolean isTransient(@InternalInsetsType int type) { |
| 157 | return mShowingTransientTypes.indexOf(type) != -1; |
| 158 | } |
| 159 | |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 160 | /** |
| 161 | * @see InsetsStateController#getInsetsForDispatch |
| 162 | */ |
| 163 | InsetsState getInsetsForDispatch(WindowState target) { |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 164 | InsetsState originalState = mStateController.getInsetsForDispatch(target); |
| 165 | InsetsState state = originalState; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 166 | for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 167 | state = new InsetsState(state); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 168 | state.setSourceVisible(mShowingTransientTypes.get(i), false); |
| 169 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 170 | if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) { |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 171 | if (state == originalState) { |
| 172 | state = new InsetsState(state); |
| 173 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 174 | state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState()); |
| 175 | } |
| 176 | if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) { |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 177 | if (state == originalState) { |
| 178 | state = new InsetsState(state); |
| 179 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 180 | state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState()); |
| 181 | } |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 182 | return state; |
| 183 | } |
| 184 | |
| 185 | void onInsetsModified(WindowState windowState, InsetsState state) { |
| 186 | mStateController.onInsetsModified(windowState, state); |
| 187 | checkAbortTransient(windowState, state); |
| 188 | if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) { |
| 189 | return; |
| 190 | } |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 191 | if (windowState == getStatusControlTarget(mFocusedWin)) { |
| 192 | mStatusBar.setVisible(state.getSource(ITYPE_STATUS_BAR).isVisible()); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 193 | } |
| 194 | if (windowState == getNavControlTarget(mFocusedWin)) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 195 | mNavBar.setVisible(state.getSource(ITYPE_NAVIGATION_BAR).isVisible()); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 196 | } |
Tiger Huang | 9ff42bd | 2020-05-01 03:27:33 +0800 | [diff] [blame] | 197 | mPolicy.updateHideNavInputEventReceiver(); |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | /** |
| 201 | * Called when a window modified the insets state. If the window set a insets source to visible |
| 202 | * while it is shown transiently, we need to abort the transient state. |
| 203 | * |
| 204 | * @param windowState who changed the insets state. |
| 205 | * @param state the modified insets state. |
| 206 | */ |
| 207 | private void checkAbortTransient(WindowState windowState, InsetsState state) { |
| 208 | if (mShowingTransientTypes.size() != 0) { |
| 209 | IntArray abortTypes = new IntArray(); |
| 210 | for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { |
| 211 | final int type = mShowingTransientTypes.get(i); |
| 212 | if (mStateController.isFakeTarget(type, windowState) |
| 213 | && state.getSource(type).isVisible()) { |
| 214 | mShowingTransientTypes.remove(i); |
| 215 | abortTypes.add(type); |
| 216 | } |
| 217 | } |
| 218 | if (abortTypes.size() > 0) { |
| 219 | mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), |
| 220 | abortTypes.toArray()); |
| 221 | updateBarControlTarget(mFocusedWin); |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 226 | private void abortTransient() { |
| 227 | mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(), |
| 228 | mShowingTransientTypes.toArray()); |
| 229 | mShowingTransientTypes.clear(); |
| 230 | updateBarControlTarget(mFocusedWin); |
| 231 | } |
| 232 | |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 233 | private @Nullable InsetsControlTarget getFakeStatusControlTarget( |
| 234 | @Nullable WindowState focused) { |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 235 | return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) { |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 239 | return getNavControlTarget(focused) == mDummyControlTarget ? focused : null; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 240 | } |
| 241 | |
Tiger Huang | 4a7835f | 2019-11-06 00:07:56 +0800 | [diff] [blame] | 242 | private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 243 | if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 244 | return mDummyControlTarget; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 245 | } |
Jorim Jaggi | 026ed75 | 2020-01-29 00:30:24 +0100 | [diff] [blame] | 246 | if (focusedWin == mPolicy.getNotificationShade()) { |
| 247 | // Notification shade has control anyways, no reason to force anything. |
| 248 | return focusedWin; |
| 249 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 250 | if (forceShowsSystemBarsForWindowingMode()) { |
| 251 | // Status bar is forcibly shown for the windowing mode which is a steady state. |
| 252 | // We don't want the client to control the status bar, and we will dispatch the real |
| 253 | // visibility of status bar to the client. |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 254 | return null; |
| 255 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 256 | if (forceShowsStatusBarTransiently()) { |
| 257 | // Status bar is forcibly shown transiently, and its new visibility won't be |
| 258 | // dispatched to the client so that we can keep the layout stable. We will dispatch the |
| 259 | // fake control to the client, so that it can re-show the bar during this scenario. |
| 260 | return mDummyControlTarget; |
| 261 | } |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 262 | return focusedWin; |
| 263 | } |
| 264 | |
| 265 | private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) { |
Tiger Huang | 332793b | 2019-10-29 23:21:27 +0800 | [diff] [blame] | 266 | if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 267 | return mDummyControlTarget; |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 268 | } |
Jorim Jaggi | 026ed75 | 2020-01-29 00:30:24 +0100 | [diff] [blame] | 269 | if (focusedWin == mPolicy.getNotificationShade()) { |
| 270 | // Notification shade has control anyways, no reason to force anything. |
| 271 | return focusedWin; |
| 272 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 273 | if (forceShowsSystemBarsForWindowingMode()) { |
| 274 | // Navigation bar is forcibly shown for the windowing mode which is a steady state. |
| 275 | // We don't want the client to control the navigation bar, and we will dispatch the real |
| 276 | // visibility of navigation bar to the client. |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 277 | return null; |
| 278 | } |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 279 | if (forceShowsNavigationBarTransiently()) { |
| 280 | // Navigation bar is forcibly shown transiently, and its new visibility won't be |
| 281 | // dispatched to the client so that we can keep the layout stable. We will dispatch the |
| 282 | // fake control to the client, so that it can re-show the bar during this scenario. |
| 283 | return mDummyControlTarget; |
| 284 | } |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 285 | return focusedWin; |
| 286 | } |
| 287 | |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 288 | private boolean forceShowsStatusBarTransiently() { |
| 289 | final WindowState win = mPolicy.getStatusBar(); |
| 290 | return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 291 | } |
| 292 | |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 293 | private boolean forceShowsNavigationBarTransiently() { |
| 294 | final WindowState win = mPolicy.getNotificationShade(); |
| 295 | return win != null |
| 296 | && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 297 | } |
| 298 | |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 299 | private boolean forceShowsSystemBarsForWindowingMode() { |
Andrii Kulian | 4c0fd0d | 2020-03-29 13:32:14 -0700 | [diff] [blame] | 300 | final boolean isDockedStackVisible = mDisplayContent.getDefaultTaskDisplayArea() |
| 301 | .isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); |
| 302 | final boolean isFreeformStackVisible = mDisplayContent.getDefaultTaskDisplayArea() |
| 303 | .isStackVisible(WINDOWING_MODE_FREEFORM); |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 304 | final boolean isResizing = mDisplayContent.getDockedDividerController().isResizing(); |
| 305 | |
| 306 | // We need to force system bars when the docked stack is visible, when the freeform stack |
| 307 | // is visible but also when we are resizing for the transitions when docked stack |
| 308 | // visibility changes. |
JianYang Liu | ae86b3f | 2020-04-03 20:20:35 -0700 | [diff] [blame] | 309 | return isDockedStackVisible |
| 310 | || isFreeformStackVisible |
| 311 | || isResizing |
| 312 | || mPolicy.getForceShowSystemBars(); |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 313 | } |
| 314 | |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 315 | @VisibleForTesting |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 316 | void startAnimation(boolean show, Runnable callback, InsetsState state) { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 317 | int typesReady = 0; |
| 318 | final SparseArray<InsetsSourceControl> controls = new SparseArray<>(); |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 319 | final IntArray showingTransientTypes = mShowingTransientTypes; |
| 320 | for (int i = showingTransientTypes.size() - 1; i >= 0; i--) { |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 321 | int type = showingTransientTypes.get(i); |
| 322 | InsetsSourceProvider provider = mStateController.getSourceProvider(type); |
Tiger Huang | b9510ef | 2020-03-03 23:03:39 +0800 | [diff] [blame] | 323 | InsetsSourceControl control = provider.getControl(mDummyControlTarget); |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 324 | if (control == null || control.getLeash() == null) { |
| 325 | continue; |
| 326 | } |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 327 | typesReady |= InsetsState.toPublicType(type); |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 328 | controls.put(control.getType(), new InsetsSourceControl(control)); |
Jorim Jaggi | 49b9f6c | 2020-03-24 22:28:38 +0100 | [diff] [blame] | 329 | state.setSourceVisible(type, show); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 330 | } |
| 331 | controlAnimationUnchecked(typesReady, controls, show, callback); |
| 332 | } |
| 333 | |
| 334 | private void controlAnimationUnchecked(int typesReady, |
| 335 | SparseArray<InsetsSourceControl> controls, boolean show, Runnable callback) { |
| 336 | InsetsPolicyAnimationControlListener listener = |
Jorim Jaggi | 5875cca | 2020-03-17 13:44:57 +0100 | [diff] [blame] | 337 | new InsetsPolicyAnimationControlListener(show, callback, typesReady); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 338 | listener.mControlCallbacks.controlAnimationUnchecked(typesReady, controls, show); |
| 339 | } |
| 340 | |
Jorim Jaggi | 956ca41 | 2019-01-07 14:49:14 +0100 | [diff] [blame] | 341 | private class BarWindow { |
| 342 | |
| 343 | private final int mId; |
| 344 | private @StatusBarManager.WindowVisibleState int mState = |
| 345 | StatusBarManager.WINDOW_STATE_SHOWING; |
| 346 | |
| 347 | BarWindow(int id) { |
| 348 | mId = id; |
| 349 | } |
| 350 | |
| 351 | private void setVisible(boolean visible) { |
| 352 | final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN; |
| 353 | if (mState != state) { |
| 354 | mState = state; |
| 355 | mPolicy.getStatusBarManagerInternal().setWindowState( |
| 356 | mDisplayContent.getDisplayId(), mId, state); |
| 357 | } |
| 358 | } |
| 359 | } |
| 360 | |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 361 | private class InsetsPolicyAnimationControlListener extends |
| 362 | InsetsController.InternalAnimationControlListener { |
| 363 | Runnable mFinishCallback; |
| 364 | InsetsPolicyAnimationControlCallbacks mControlCallbacks; |
| 365 | |
Jorim Jaggi | 5875cca | 2020-03-17 13:44:57 +0100 | [diff] [blame] | 366 | InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) { |
| 367 | super(show, false /* hasCallbacks */, types); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 368 | mFinishCallback = finishCallback; |
| 369 | mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this); |
| 370 | } |
| 371 | |
| 372 | @Override |
| 373 | protected void onAnimationFinish() { |
| 374 | super.onAnimationFinish(); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 375 | DisplayThread.getHandler().post(mFinishCallback); |
| 376 | } |
| 377 | |
| 378 | private class InsetsPolicyAnimationControlCallbacks implements |
| 379 | InsetsAnimationControlCallbacks { |
| 380 | private InsetsAnimationControlImpl mAnimationControl = null; |
| 381 | private InsetsPolicyAnimationControlListener mListener; |
| 382 | |
| 383 | InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener) { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 384 | mListener = listener; |
| 385 | } |
| 386 | |
| 387 | private void controlAnimationUnchecked(int typesReady, |
| 388 | SparseArray<InsetsSourceControl> controls, boolean show) { |
| 389 | if (typesReady == 0) { |
| 390 | // nothing to animate. |
| 391 | return; |
| 392 | } |
| 393 | mAnimatingShown = show; |
| 394 | |
| 395 | mAnimationControl = new InsetsAnimationControlImpl(controls, |
| 396 | mFocusedWin.getDisplayContent().getBounds(), getState(), |
| 397 | mListener, typesReady, this, mListener.getDurationMs(), |
Jorim Jaggi | 5875cca | 2020-03-17 13:44:57 +0100 | [diff] [blame] | 398 | InsetsController.SYSTEM_BARS_INTERPOLATOR, |
Tarandeep Singh | b9538cd | 2020-02-20 17:51:18 -0800 | [diff] [blame] | 399 | show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE); |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 400 | SurfaceAnimationThread.getHandler().post( |
| 401 | () -> mListener.onReady(mAnimationControl, typesReady)); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 402 | } |
| 403 | |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 404 | /** Called on SurfaceAnimationThread without global WM lock held. */ |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 405 | @Override |
Adrian Roos | 6a4448f | 2020-04-01 15:01:08 +0200 | [diff] [blame] | 406 | public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 407 | InsetsState state = getState(); |
| 408 | if (mAnimationControl.applyChangeInsets(state)) { |
| 409 | mAnimationControl.finish(mAnimatingShown); |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | @Override |
Jorim Jaggi | 6d5c801 | 2020-02-28 01:40:27 +0100 | [diff] [blame] | 414 | public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 415 | // Nothing's needed here. Finish steps is handled in the listener |
| 416 | // onAnimationFinished callback. |
| 417 | } |
| 418 | |
| 419 | /** |
| 420 | * This method will return a state with fullscreen frame override. No need to make copy |
| 421 | * after getting state from this method. |
| 422 | * @return The client insets state with full display frame override. |
| 423 | */ |
| 424 | private InsetsState getState() { |
| 425 | // To animate the transient animation correctly, we need to let the state hold |
| 426 | // the full display frame. |
| 427 | InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(), |
| 428 | true); |
| 429 | overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds()); |
| 430 | return overrideState; |
| 431 | } |
| 432 | |
Tiger Huang | a1663403 | 2020-02-05 17:10:03 +0800 | [diff] [blame] | 433 | /** Called on SurfaceAnimationThread without global WM lock held. */ |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 434 | @Override |
| 435 | public void applySurfaceParams( |
| 436 | final SyncRtSurfaceTransactionApplier.SurfaceParams... params) { |
| 437 | SurfaceControl.Transaction t = new SurfaceControl.Transaction(); |
| 438 | for (int i = params.length - 1; i >= 0; i--) { |
| 439 | SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i]; |
| 440 | applyParams(t, surfaceParams, mTmpFloat9); |
| 441 | } |
| 442 | t.apply(); |
Jorim Jaggi | 6d5c801 | 2020-02-28 01:40:27 +0100 | [diff] [blame] | 443 | t.close(); |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 444 | } |
| 445 | |
Rob Carr | 3a367c4 | 2020-03-10 15:51:35 -0700 | [diff] [blame] | 446 | // Since we don't push applySurfaceParams to a Handler-queue we don't need |
| 447 | // to push release in this case. |
| 448 | @Override |
| 449 | public void releaseSurfaceControlFromRt(SurfaceControl sc) { |
| 450 | sc.release(); |
| 451 | } |
| 452 | |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 453 | @Override |
| 454 | public void startAnimation(InsetsAnimationControlImpl controller, |
| 455 | WindowInsetsAnimationControlListener listener, int types, |
Adrian Roos | db5b0c2 | 2020-02-12 15:05:27 -0800 | [diff] [blame] | 456 | WindowInsetsAnimation animation, |
Jorim Jaggi | 6d5c801 | 2020-02-28 01:40:27 +0100 | [diff] [blame] | 457 | Bounds bounds) { |
Yunfan Chen | b5d2db7 | 2019-12-06 15:43:43 +0900 | [diff] [blame] | 458 | } |
| 459 | } |
| 460 | } |
Jorim Jaggi | 2862047 | 2019-01-02 23:21:49 +0100 | [diff] [blame] | 461 | } |