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 android.server.wm;
18 
19 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
20 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
22 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
23 import static android.view.Display.DEFAULT_DISPLAY;
24 
25 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
26 
27 import static org.junit.Assert.assertEquals;
28 
29 import android.app.Activity;
30 import android.app.ActivityOptions;
31 import android.content.Intent;
32 import android.os.Bundle;
33 
34 import com.android.compatibility.common.util.SystemUtil;
35 
36 import java.lang.reflect.Array;
37 
38 import javax.annotation.concurrent.GuardedBy;
39 
40 public class WindowManagerTestBase extends MultiDisplayTestBase {
41     protected static final long TIMEOUT_WINDOW_FOCUS_CHANGED = 3000; // milliseconds
42 
startActivity(Class<T> cls)43     public static <T extends FocusableActivity> T startActivity(Class<T> cls) {
44         return startActivity(cls, DEFAULT_DISPLAY);
45     }
46 
startActivity(Class<T> cls, int displayId)47     protected static <T extends FocusableActivity> T startActivity(Class<T> cls, int displayId) {
48         return startActivity(cls, displayId, true /* hasFocus */);
49     }
50 
startActivity( Class<T> cls, int displayId, boolean hasFocus)51     protected static <T extends FocusableActivity> T startActivity(
52             Class<T> cls, int displayId, boolean hasFocus) {
53         return startActivity(cls, displayId, hasFocus, WINDOWING_MODE_UNDEFINED);
54     }
55 
startActivityInWindowingMode( Class<T> cls, int windowingMode)56     public static <T extends FocusableActivity> T startActivityInWindowingMode(
57             Class<T> cls, int windowingMode) {
58         return startActivity(cls, DEFAULT_DISPLAY, true /* hasFocus */, windowingMode);
59     }
60 
startActivityInWindowingModeFullScreen( Class<T> cls)61     protected static <T extends FocusableActivity> T startActivityInWindowingModeFullScreen(
62             Class<T> cls) {
63         return startActivity(cls, DEFAULT_DISPLAY, true /* hasFocus */, WINDOWING_MODE_FULLSCREEN);
64     }
65 
startActivity( Class<T> cls, int displayId, boolean hasFocus, int windowingMode)66     public static <T extends FocusableActivity> T startActivity(
67             Class<T> cls, int displayId, boolean hasFocus, int windowingMode) {
68         return startActivity(cls, displayId, hasFocus, windowingMode, INVALID_STACK_ID);
69     }
70 
startActivity( Class<T> cls, int displayId, boolean hasFocus, int windowingMode, int taskId)71     protected static <T extends FocusableActivity> T startActivity(
72             Class<T> cls, int displayId, boolean hasFocus, int windowingMode, int taskId) {
73         final Bundle options;
74         if (displayId == DEFAULT_DISPLAY && windowingMode == WINDOWING_MODE_UNDEFINED
75                 && taskId == INVALID_STACK_ID) {
76             options = null;
77         } else {
78             final ActivityOptions ap= ActivityOptions.makeBasic();
79             if (displayId != DEFAULT_DISPLAY) ap.setLaunchDisplayId(displayId);
80             if (windowingMode != WINDOWING_MODE_UNDEFINED) ap.setLaunchWindowingMode(windowingMode);
81             if (taskId != INVALID_STACK_ID) ap.setLaunchTaskId(taskId);
82             options = ap.toBundle();
83         }
84         final T[] activity = (T[]) Array.newInstance(FocusableActivity.class, 1);
85         SystemUtil.runWithShellPermissionIdentity(() -> {
86             activity[0] = (T) getInstrumentation().startActivitySync(
87                     new Intent(getInstrumentation().getTargetContext(), cls)
88                             .addFlags(FLAG_ACTIVITY_NEW_TASK), options);
89             activity[0].waitAndAssertWindowFocusState(hasFocus);
90         });
91         return activity[0];
92     }
93 
94     public static class FocusableActivity extends Activity {
95         private final Object mLockWindowFocus = new Object();
96 
97         @GuardedBy("mLockWindowFocus")
98         private boolean mHasWindowFocus;
99 
getLogTag()100         public final String getLogTag() {
101             return ComponentNameUtils.getLogTag(getComponentName());
102         }
103 
104         @Override
onWindowFocusChanged(boolean hasFocus)105         public void onWindowFocusChanged(boolean hasFocus) {
106             StateLogger.logAlways(getLogTag() + " onWindowFocusChanged: " + hasFocus);
107             synchronized (mLockWindowFocus) {
108                 mHasWindowFocus = hasFocus;
109                 mLockWindowFocus.notify();
110             }
111         }
112 
assertWindowFocusState(boolean hasFocus)113         void assertWindowFocusState(boolean hasFocus) {
114             synchronized (mLockWindowFocus) {
115                 assertEquals(getLogTag() + " must" + (hasFocus ? "" : " not")
116                         + " have window focus.", hasFocus, mHasWindowFocus);
117             }
118         }
119 
waitAndAssertWindowFocusState(boolean hasFocus)120         public void waitAndAssertWindowFocusState(boolean hasFocus) {
121             synchronized (mLockWindowFocus) {
122                 if (mHasWindowFocus != hasFocus) {
123                     try {
124                         mLockWindowFocus.wait(TIMEOUT_WINDOW_FOCUS_CHANGED);
125                     } catch (InterruptedException e) {
126                     }
127                 }
128             }
129             assertWindowFocusState(hasFocus);
130         }
131     }
132 }
133