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