1 /* 2 * Copyright (C) 2020 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.inputmethodservice.cts.devicetest; 18 19 import static org.junit.Assert.assertTrue; 20 import static org.junit.Assume.assumeTrue; 21 22 import android.app.Instrumentation; 23 import android.app.UiAutomation; 24 import android.inputmethodservice.cts.ime.Watermark; 25 import android.os.SystemClock; 26 27 import androidx.annotation.NonNull; 28 import androidx.test.platform.app.InstrumentationRegistry; 29 30 import java.util.concurrent.CountDownLatch; 31 import java.util.concurrent.TimeUnit; 32 33 /** 34 * Provides utility methods to test whether test IMEs are visible to the user or not. 35 */ 36 final class InputMethodVisibilityVerifier { 37 38 private static final long SCREENSHOT_DELAY = 100; // msec 39 private static final long SCREENSHOT_TIME_SLICE = 500; // msec 40 41 @NonNull containsWatermark(@onNull UiAutomation uiAutomation, @NonNull Watermark watermark)42 private static boolean containsWatermark(@NonNull UiAutomation uiAutomation, 43 @NonNull Watermark watermark) { 44 return watermark.isContainedIn(uiAutomation.takeScreenshot()); 45 } 46 waitUntilWatermarkBecomesVisible(long timeout, @NonNull Watermark watermark)47 private static boolean waitUntilWatermarkBecomesVisible(long timeout, 48 @NonNull Watermark watermark) { 49 final long startTime = SystemClock.elapsedRealtime(); 50 SystemClock.sleep(SCREENSHOT_DELAY); 51 52 final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 53 54 // Wait until the main thread becomes idle. 55 final CountDownLatch latch = new CountDownLatch(1); 56 instrumentation.waitForIdle(latch::countDown); 57 try { 58 if (!latch.await(timeout, TimeUnit.MILLISECONDS)) { 59 return false; 60 } 61 } catch (InterruptedException e) { 62 } 63 64 final UiAutomation uiAutomation = instrumentation.getUiAutomation(); 65 66 // Make sure the watermark is tested at least two times, regardless of the timeout. 67 boolean firstCheck = true; 68 while (true) { 69 final boolean lastCheck; 70 if (firstCheck) { 71 firstCheck = false; 72 lastCheck = false; 73 } else { 74 SystemClock.sleep(SCREENSHOT_TIME_SLICE); 75 lastCheck = (SystemClock.elapsedRealtime() - startTime) >= timeout; 76 } 77 if (containsWatermark(uiAutomation, watermark)) { 78 return true; 79 } 80 if (lastCheck) { 81 return false; 82 } 83 } 84 } 85 86 /** 87 * Asserts that IME1 is visible to the user. 88 * 89 * @param timeout timeout in milliseconds. 90 */ assertIme1Visible(long timeout)91 static void assertIme1Visible(long timeout) { 92 assertTrue(waitUntilWatermarkBecomesVisible(timeout, Watermark.IME1)); 93 } 94 95 /** 96 * Assumes that IME1 is visible to the user. 97 * 98 * @param message message to be shown when the assumption is not satisfied. 99 * @param timeout timeout in milliseconds. 100 */ assumeIme1Visible(String message, long timeout)101 static void assumeIme1Visible(String message, long timeout) { 102 assumeTrue(message, waitUntilWatermarkBecomesVisible(timeout, Watermark.IME1)); 103 } 104 105 /** 106 * Asserts that IME2 is visible to the user. 107 * 108 * @param timeout timeout in milliseconds. 109 */ assertIme2Visible(long timeout)110 static void assertIme2Visible(long timeout) { 111 assertTrue(waitUntilWatermarkBecomesVisible(timeout, Watermark.IME2)); 112 } 113 } 114