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 
19 import static android.app.AppOpsManager.OP_NONE;
20 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
21 
22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
23 import static com.android.server.wm.WindowContainer.POSITION_TOP;
24 
25 import android.app.ActivityManager;
26 import android.content.ComponentName;
27 import android.os.Build;
28 import android.os.IBinder;
29 import android.view.IApplicationToken;
30 import android.view.IWindow;
31 import android.view.WindowManager;
32 
33 /**
34  * A collection of static functions that provide access to WindowManager related test functionality.
35  */
36 class WindowTestUtils {
37     private static int sNextTaskId = 0;
38 
39     /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
createTaskInStack(WindowManagerService service, TaskStack stack, int userId)40     static Task createTaskInStack(WindowManagerService service, TaskStack stack,
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 
50     /** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */
createAppWindowTokenInTask(DisplayContent dc, Task task)51     static TestAppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
52         final TestAppWindowToken newToken = createTestAppWindowToken(dc);
53         task.addChild(newToken, POSITION_TOP);
54         return newToken;
55     }
56 
createTestAppWindowToken(DisplayContent dc)57     static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
58         synchronized (dc.mWmService.mGlobalLock) {
59             return new TestAppWindowToken(dc);
60         }
61     }
62 
63     /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
64     static class TestAppWindowToken extends AppWindowToken {
65         boolean mOnTop = false;
66 
TestAppWindowToken(DisplayContent dc)67         private TestAppWindowToken(DisplayContent dc) {
68             super(dc.mWmService, new IApplicationToken.Stub() {
69                 @Override
70                 public String getName() {
71                     return null;
72                 }
73             }, new ComponentName("", ""), false, dc, true /* fillsParent */);
74             mTargetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT;
75             mActivityRecord = mock(ActivityRecord.class);
76             mActivityRecord.app = mock(WindowProcessController.class);
77         }
78 
getWindowsCount()79         int getWindowsCount() {
80             return mChildren.size();
81         }
82 
hasWindow(WindowState w)83         boolean hasWindow(WindowState w) {
84             return mChildren.contains(w);
85         }
86 
getFirstChild()87         WindowState getFirstChild() {
88             return mChildren.peekFirst();
89         }
90 
getLastChild()91         WindowState getLastChild() {
92             return mChildren.peekLast();
93         }
94 
95         @Override
isOnTop()96         boolean isOnTop() {
97             return mOnTop;
98         }
99 
100     }
101 
createTestWindowToken(int type, DisplayContent dc)102     static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
103         return createTestWindowToken(type, dc, false /* persistOnEmpty */);
104     }
105 
createTestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty)106     static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
107             boolean persistOnEmpty) {
108         synchronized (dc.mWmService.mGlobalLock) {
109             return new TestWindowToken(type, dc, persistOnEmpty);
110         }
111     }
112 
113     /* Used so we can gain access to some protected members of the {@link WindowToken} class */
114     static class TestWindowToken extends WindowToken {
115 
TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty)116         private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
117             super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
118                     false /* ownerCanManageAppTokens */);
119         }
120 
getWindowsCount()121         int getWindowsCount() {
122             return mChildren.size();
123         }
124 
hasWindow(WindowState w)125         boolean hasWindow(WindowState w) {
126             return mChildren.contains(w);
127         }
128     }
129 
130     /* Used so we can gain access to some protected members of the {@link Task} class */
131     static class TestTask extends Task {
132         boolean mShouldDeferRemoval = false;
133         boolean mOnDisplayChangedCalled = false;
134         private boolean mIsAnimating = false;
135 
TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode, boolean supportsPictureInPicture, TaskRecord taskRecord)136         TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
137                 int resizeMode, boolean supportsPictureInPicture,
138                 TaskRecord taskRecord) {
139             super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
140                     new ActivityManager.TaskDescription(), taskRecord);
141             stack.addTask(this, POSITION_TOP);
142         }
143 
shouldDeferRemoval()144         boolean shouldDeferRemoval() {
145             return mShouldDeferRemoval;
146         }
147 
positionInParent()148         int positionInParent() {
149             return getParent().mChildren.indexOf(this);
150         }
151 
152         @Override
onDisplayChanged(DisplayContent dc)153         void onDisplayChanged(DisplayContent dc) {
154             super.onDisplayChanged(dc);
155             mOnDisplayChangedCalled = true;
156         }
157 
158         @Override
isSelfAnimating()159         boolean isSelfAnimating() {
160             return mIsAnimating;
161         }
162 
setLocalIsAnimating(boolean isAnimating)163         void setLocalIsAnimating(boolean isAnimating) {
164             mIsAnimating = isAnimating;
165         }
166     }
167 
createTestTask(TaskStack stack)168     static TestTask createTestTask(TaskStack stack) {
169         return new TestTask(sNextTaskId++, stack, 0, stack.mWmService, RESIZE_MODE_UNRESIZEABLE,
170                 false, mock(TaskRecord.class));
171     }
172 
173     /** Used to track resize reports. */
174     static class TestWindowState extends WindowState {
175         boolean mResizeReported;
176 
TestWindowState(WindowManagerService service, Session session, IWindow window, WindowManager.LayoutParams attrs, WindowToken token)177         TestWindowState(WindowManagerService service, Session session, IWindow window,
178                 WindowManager.LayoutParams attrs, WindowToken token) {
179             super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
180                     false /* ownerCanAddInternalSystemWindow */);
181         }
182 
183         @Override
reportResized()184         void reportResized() {
185             super.reportResized();
186             mResizeReported = true;
187         }
188 
189         @Override
isGoneForLayoutLw()190         public boolean isGoneForLayoutLw() {
191             return false;
192         }
193 
194         @Override
updateResizingWindowIfNeeded()195         void updateResizingWindowIfNeeded() {
196             // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
197             // the system that it can actually update the window.
198             boolean hadSurface = mHasSurface;
199             mHasSurface = true;
200 
201             super.updateResizingWindowIfNeeded();
202 
203             mHasSurface = hadSurface;
204         }
205     }
206 }
207