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