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.content.Intent.FLAG_ACTIVITY_NEW_TASK;
20 import static android.server.wm.UiDeviceUtils.pressHomeButton;
21 import static android.server.wm.UiDeviceUtils.pressUnlockButton;
22 import static android.server.wm.UiDeviceUtils.pressWakeupButton;
23 import static android.view.Display.DEFAULT_DISPLAY;
24 
25 import static androidx.test.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 org.junit.Before;
35 
36 import javax.annotation.concurrent.GuardedBy;
37 
38 public class WindowManagerTestBase {
39     static final long TIMEOUT_WINDOW_FOCUS_CHANGED = 1000; // milliseconds
40 
41     @Before
setupBase()42     public void setupBase() {
43         pressWakeupButton();
44         pressUnlockButton();
45         pressHomeButton();
46     }
47 
startActivity(Class<T> cls)48     static <T extends FocusableActivity> T startActivity(Class<T> cls) throws InterruptedException {
49         return startActivity(cls, DEFAULT_DISPLAY);
50     }
51 
startActivity(Class<T> cls, int displayId)52     static <T extends FocusableActivity> T startActivity(Class<T> cls, int displayId)
53             throws InterruptedException {
54         final Bundle options = (displayId == DEFAULT_DISPLAY
55                 ? null : ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle());
56         final T activity = (T) getInstrumentation().startActivitySync(
57                 new Intent(getInstrumentation().getTargetContext(), cls)
58                         .addFlags(FLAG_ACTIVITY_NEW_TASK), options);
59         activity.waitAndAssertWindowFocusState(true /* hasFocus */);
60         return activity;
61     }
62 
63     static class FocusableActivity extends Activity {
64         private final Object mLockWindowFocus = new Object();
65 
66         @GuardedBy("mLockWindowFocus")
67         private boolean mHasWindowFocus;
68 
getLogTag()69         final String getLogTag() {
70             return ComponentNameUtils.getLogTag(getComponentName());
71         }
72 
73         @Override
onWindowFocusChanged(boolean hasFocus)74         public void onWindowFocusChanged(boolean hasFocus) {
75             synchronized (mLockWindowFocus) {
76                 mHasWindowFocus = hasFocus;
77                 mLockWindowFocus.notify();
78             }
79         }
80 
assertWindowFocusState(boolean hasFocus)81         void assertWindowFocusState(boolean hasFocus) {
82             synchronized (mLockWindowFocus) {
83                 assertEquals(getLogTag() + " must" + (hasFocus ? "" : " not")
84                         + " have window focus.", hasFocus, mHasWindowFocus);
85             }
86         }
87 
waitAndAssertWindowFocusState(boolean hasFocus)88         void waitAndAssertWindowFocusState(boolean hasFocus) throws InterruptedException {
89             synchronized (mLockWindowFocus) {
90                 if (mHasWindowFocus != hasFocus) {
91                     mLockWindowFocus.wait(TIMEOUT_WINDOW_FOCUS_CHANGED);
92                 }
93             }
94             assertWindowFocusState(hasFocus);
95         }
96     }
97 }
98