Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 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 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 19 | import static android.app.AppOpsManager.OP_NONE; |
| 20 | import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; |
| 21 | |
Tadashi G. Takaoka | a7a6695 | 2018-11-16 15:04:21 +0900 | [diff] [blame] | 22 | import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 23 | import static com.android.server.wm.WindowContainer.POSITION_TOP; |
Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 24 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 25 | import android.app.ActivityManager; |
| 26 | import android.content.ComponentName; |
Tiger Huang | 51c5a1d | 2018-12-11 20:24:51 +0800 | [diff] [blame] | 27 | import android.os.Build; |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 28 | import android.os.IBinder; |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 29 | import android.view.IApplicationToken; |
| 30 | import android.view.IWindow; |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 31 | import android.view.WindowManager; |
Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 32 | |
Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 33 | /** |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 34 | * A collection of static functions that provide access to WindowManager related test functionality. |
Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 35 | */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 36 | class WindowTestUtils { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 37 | private static int sNextTaskId = 0; |
Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 38 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 39 | /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 40 | static Task createTaskInStack(WindowManagerService service, TaskStack stack, |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 41 | int userId) { |
| 42 | synchronized (service.mGlobalLock) { |
| 43 | final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false, |
| 44 | new ActivityManager.TaskDescription(), null); |
| 45 | stack.addTask(newTask, POSITION_TOP); |
| 46 | return newTask; |
| 47 | } |
| 48 | } |
| 49 | |
Yunfan Chen | 0e7aff9 | 2018-12-05 16:35:32 -0800 | [diff] [blame] | 50 | /** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 51 | static TestAppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) { |
Yunfan Chen | 0e7aff9 | 2018-12-05 16:35:32 -0800 | [diff] [blame] | 52 | final TestAppWindowToken newToken = createTestAppWindowToken(dc); |
| 53 | task.addChild(newToken, POSITION_TOP); |
| 54 | return newToken; |
| 55 | } |
| 56 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 57 | static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) { |
Wale Ogunwale | 8b19de9 | 2018-11-29 19:58:26 -0800 | [diff] [blame] | 58 | synchronized (dc.mWmService.mGlobalLock) { |
Vishnu Nair | f77d53d | 2019-02-20 14:38:50 -0800 | [diff] [blame] | 59 | return new TestAppWindowToken(dc, true /* skipOnParentChanged */); |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | static TestAppWindowToken createTestAppWindowToken(DisplayContent dc, |
| 64 | boolean skipOnParentChanged) { |
| 65 | synchronized (dc.mWmService.mGlobalLock) { |
| 66 | return new TestAppWindowToken(dc, skipOnParentChanged); |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 67 | } |
| 68 | } |
| 69 | |
| 70 | /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 71 | static class TestAppWindowToken extends AppWindowToken { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 72 | boolean mOnTop = false; |
Riddle Hsu | b398da3 | 2019-01-21 21:48:16 +0800 | [diff] [blame] | 73 | private boolean mSkipPrepareSurfaces; |
Riddle Hsu | 3a4bb61 | 2019-01-31 00:02:22 +0800 | [diff] [blame] | 74 | boolean mSkipOnParentChanged = true; |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 75 | |
Vishnu Nair | f77d53d | 2019-02-20 14:38:50 -0800 | [diff] [blame] | 76 | private TestAppWindowToken(DisplayContent dc, boolean skipOnParentChanged) { |
Wale Ogunwale | 8b19de9 | 2018-11-29 19:58:26 -0800 | [diff] [blame] | 77 | super(dc.mWmService, new IApplicationToken.Stub() { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 78 | @Override |
| 79 | public String getName() { |
| 80 | return null; |
| 81 | } |
| 82 | }, new ComponentName("", ""), false, dc, true /* fillsParent */); |
Tiger Huang | 51c5a1d | 2018-12-11 20:24:51 +0800 | [diff] [blame] | 83 | mTargetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT; |
Vishnu Nair | f77d53d | 2019-02-20 14:38:50 -0800 | [diff] [blame] | 84 | mSkipOnParentChanged = skipOnParentChanged; |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 85 | } |
| 86 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 87 | int getWindowsCount() { |
| 88 | return mChildren.size(); |
| 89 | } |
| 90 | |
| 91 | boolean hasWindow(WindowState w) { |
| 92 | return mChildren.contains(w); |
| 93 | } |
| 94 | |
| 95 | WindowState getFirstChild() { |
| 96 | return mChildren.peekFirst(); |
| 97 | } |
| 98 | |
| 99 | WindowState getLastChild() { |
| 100 | return mChildren.peekLast(); |
| 101 | } |
| 102 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 103 | @Override |
Riddle Hsu | 3a4bb61 | 2019-01-31 00:02:22 +0800 | [diff] [blame] | 104 | void onParentChanged() { |
| 105 | if (!mSkipOnParentChanged) { |
| 106 | super.onParentChanged(); |
| 107 | } else { |
| 108 | updateConfigurationFromParent(this); |
Evan Rosky | 966759f | 2019-01-15 10:33:58 -0800 | [diff] [blame] | 109 | } |
Yunfan Chen | 279f558 | 2018-12-12 15:24:50 -0800 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | @Override |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 113 | boolean isOnTop() { |
| 114 | return mOnTop; |
| 115 | } |
| 116 | |
Riddle Hsu | b398da3 | 2019-01-21 21:48:16 +0800 | [diff] [blame] | 117 | @Override |
| 118 | void prepareSurfaces() { |
| 119 | if (!mSkipPrepareSurfaces) { |
| 120 | super.prepareSurfaces(); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | void setSkipPrepareSurfaces(boolean ignore) { |
| 125 | mSkipPrepareSurfaces = ignore; |
| 126 | } |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 127 | } |
| 128 | |
Riddle Hsu | 3a4bb61 | 2019-01-31 00:02:22 +0800 | [diff] [blame] | 129 | /** |
| 130 | * Used when we don't want to perform surface related operation in |
| 131 | * {@link WindowContainer#onParentChanged} or the overridden method, but the configuration |
| 132 | * still needs to propagate from parent. |
| 133 | * |
| 134 | * @see ConfigurationContainer#onParentChanged |
| 135 | */ |
| 136 | static void updateConfigurationFromParent(WindowContainer container) { |
| 137 | final WindowContainer parent = container.getParent(); |
| 138 | if (parent != null) { |
| 139 | container.onConfigurationChanged(parent.getConfiguration()); |
| 140 | container.onMergedOverrideConfigurationChanged(); |
| 141 | } |
| 142 | } |
| 143 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 144 | static TestWindowToken createTestWindowToken(int type, DisplayContent dc) { |
| 145 | return createTestWindowToken(type, dc, false /* persistOnEmpty */); |
| 146 | } |
| 147 | |
| 148 | static TestWindowToken createTestWindowToken(int type, DisplayContent dc, |
| 149 | boolean persistOnEmpty) { |
Wale Ogunwale | 8b19de9 | 2018-11-29 19:58:26 -0800 | [diff] [blame] | 150 | synchronized (dc.mWmService.mGlobalLock) { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 151 | return new TestWindowToken(type, dc, persistOnEmpty); |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | /* Used so we can gain access to some protected members of the {@link WindowToken} class */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 156 | static class TestWindowToken extends WindowToken { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 157 | |
| 158 | private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) { |
Wale Ogunwale | 8b19de9 | 2018-11-29 19:58:26 -0800 | [diff] [blame] | 159 | super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc, |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 160 | false /* ownerCanManageAppTokens */); |
| 161 | } |
| 162 | |
| 163 | int getWindowsCount() { |
| 164 | return mChildren.size(); |
| 165 | } |
| 166 | |
| 167 | boolean hasWindow(WindowState w) { |
| 168 | return mChildren.contains(w); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | /* Used so we can gain access to some protected members of the {@link Task} class */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 173 | static class TestTask extends Task { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 174 | boolean mShouldDeferRemoval = false; |
| 175 | boolean mOnDisplayChangedCalled = false; |
| 176 | private boolean mIsAnimating = false; |
| 177 | |
| 178 | TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, |
| 179 | int resizeMode, boolean supportsPictureInPicture, |
Yunfan Chen | 0e7aff9 | 2018-12-05 16:35:32 -0800 | [diff] [blame] | 180 | TaskRecord taskRecord) { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 181 | super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture, |
Yunfan Chen | 0e7aff9 | 2018-12-05 16:35:32 -0800 | [diff] [blame] | 182 | new ActivityManager.TaskDescription(), taskRecord); |
| 183 | stack.addTask(this, POSITION_TOP); |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | boolean shouldDeferRemoval() { |
| 187 | return mShouldDeferRemoval; |
| 188 | } |
| 189 | |
| 190 | int positionInParent() { |
| 191 | return getParent().mChildren.indexOf(this); |
| 192 | } |
| 193 | |
| 194 | @Override |
| 195 | void onDisplayChanged(DisplayContent dc) { |
| 196 | super.onDisplayChanged(dc); |
| 197 | mOnDisplayChangedCalled = true; |
| 198 | } |
| 199 | |
| 200 | @Override |
| 201 | boolean isSelfAnimating() { |
| 202 | return mIsAnimating; |
| 203 | } |
| 204 | |
| 205 | void setLocalIsAnimating(boolean isAnimating) { |
| 206 | mIsAnimating = isAnimating; |
| 207 | } |
| 208 | } |
| 209 | |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 210 | static TestTask createTestTask(TaskStack stack) { |
Yunfan Chen | 279f558 | 2018-12-12 15:24:50 -0800 | [diff] [blame] | 211 | return new TestTask(sNextTaskId++, stack, 0, stack.mWmService, RESIZE_MODE_UNRESIZEABLE, |
| 212 | false, mock(TaskRecord.class)); |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 213 | } |
| 214 | |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 215 | /** Used to track resize reports. */ |
Tadashi G. Takaoka | d7aa79a | 2019-02-08 17:42:37 +0900 | [diff] [blame] | 216 | static class TestWindowState extends WindowState { |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 217 | boolean mResizeReported; |
| 218 | |
| 219 | TestWindowState(WindowManagerService service, Session session, IWindow window, |
| 220 | WindowManager.LayoutParams attrs, WindowToken token) { |
| 221 | super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0, |
| 222 | false /* ownerCanAddInternalSystemWindow */); |
| 223 | } |
| 224 | |
| 225 | @Override |
| 226 | void reportResized() { |
| 227 | super.reportResized(); |
| 228 | mResizeReported = true; |
| 229 | } |
| 230 | |
| 231 | @Override |
| 232 | public boolean isGoneForLayoutLw() { |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | @Override |
| 237 | void updateResizingWindowIfNeeded() { |
| 238 | // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive |
| 239 | // the system that it can actually update the window. |
| 240 | boolean hadSurface = mHasSurface; |
| 241 | mHasSurface = true; |
| 242 | |
| 243 | super.updateResizingWindowIfNeeded(); |
| 244 | |
| 245 | mHasSurface = hadSurface; |
| 246 | } |
Yunfan Chen | 279f558 | 2018-12-12 15:24:50 -0800 | [diff] [blame] | 247 | |
| 248 | @Override |
Riddle Hsu | 3a4bb61 | 2019-01-31 00:02:22 +0800 | [diff] [blame] | 249 | void onParentChanged() { |
| 250 | updateConfigurationFromParent(this); |
Yunfan Chen | 279f558 | 2018-12-12 15:24:50 -0800 | [diff] [blame] | 251 | } |
Tadashi G. Takaoka | bf0d57b | 2018-11-19 16:09:58 +0900 | [diff] [blame] | 252 | } |
Tadashi G. Takaoka | 74ccec2 | 2018-10-23 11:07:13 +0900 | [diff] [blame] | 253 | } |