1 /* 2 * Copyright (C) 2017 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.autofillservice.cts; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import android.app.Activity; 23 import android.graphics.Bitmap; 24 import android.graphics.Rect; 25 import android.view.PixelCopy; 26 import android.view.View; 27 import android.view.autofill.AutofillManager; 28 29 import com.android.compatibility.common.util.SynchronousPixelCopy; 30 31 import java.util.concurrent.CountDownLatch; 32 import java.util.concurrent.TimeUnit; 33 34 /** 35 * Base class for all activities in this test suite 36 */ 37 abstract class AbstractAutoFillActivity extends Activity { 38 39 private MyAutofillCallback mCallback; 40 41 /** 42 * Run an action in the UI thread, and blocks caller until the action is finished. 43 */ syncRunOnUiThread(Runnable action)44 public final void syncRunOnUiThread(Runnable action) { 45 syncRunOnUiThread(action, Timeouts.UI_TIMEOUT.ms()); 46 } 47 48 /** 49 * Run an action in the UI thread, and blocks caller until the action is finished or it times 50 * out. 51 */ syncRunOnUiThread(Runnable action, long timeoutMs)52 public final void syncRunOnUiThread(Runnable action, long timeoutMs) { 53 final CountDownLatch latch = new CountDownLatch(1); 54 runOnUiThread(() -> { 55 action.run(); 56 latch.countDown(); 57 }); 58 try { 59 if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) { 60 throw new RetryableException("action on UI thread timed out after %d ms", 61 timeoutMs); 62 } 63 } catch (InterruptedException e) { 64 Thread.currentThread().interrupt(); 65 throw new RuntimeException("Interrupted", e); 66 } 67 } 68 getAutofillManager()69 protected AutofillManager getAutofillManager() { 70 return getSystemService(AutofillManager.class); 71 } 72 73 /** 74 * Takes a screenshot from the whole activity. 75 * 76 * <p><b>Note:</b> this screenshot only contains the contents of the activity, it doesn't 77 * include the autofill UIs; if you need to check that, please use 78 * {@link UiBot#takeScreenshot()} instead. 79 */ takeScreenshot()80 public Bitmap takeScreenshot() { 81 return takeScreenshot(findViewById(android.R.id.content).getRootView()); 82 } 83 84 /** 85 * Takes a screenshot from the a view. 86 */ takeScreenshot(View view)87 public Bitmap takeScreenshot(View view) { 88 final Rect srcRect = new Rect(); 89 syncRunOnUiThread(() -> view.getGlobalVisibleRect(srcRect)); 90 final Bitmap dest = Bitmap.createBitmap( 91 srcRect.width(), srcRect.height(), Bitmap.Config.ARGB_8888); 92 93 final SynchronousPixelCopy copy = new SynchronousPixelCopy(); 94 final int copyResult = copy.request(getWindow(), srcRect, dest); 95 assertThat(copyResult).isEqualTo(PixelCopy.SUCCESS); 96 97 return dest; 98 } 99 100 /** 101 * Registers and returns a custom callback for autofill events. 102 * 103 * <p>Note: caller doesn't need to call {@link #unregisterCallback()}, it will be automatically 104 * unregistered on {@link #finish()}. 105 */ registerCallback()106 protected MyAutofillCallback registerCallback() { 107 assertWithMessage("already registered").that(mCallback).isNull(); 108 mCallback = new MyAutofillCallback(); 109 getAutofillManager().registerCallback(mCallback); 110 return mCallback; 111 } 112 113 /** 114 * Unregister the callback from the {@link AutofillManager}. 115 * 116 * <p>This method just neeed to be called when a test case wants to explicitly test the behavior 117 * of the activity when the callback is unregistered. 118 */ unregisterCallback()119 protected void unregisterCallback() { 120 assertWithMessage("not registered").that(mCallback).isNotNull(); 121 unregisterNonNullCallback(); 122 } 123 unregisterNonNullCallback()124 private void unregisterNonNullCallback() { 125 getAutofillManager().unregisterCallback(mCallback); 126 mCallback = null; 127 } 128 129 @Override finish()130 public void finish() { 131 if (mCallback != null) { 132 unregisterNonNullCallback(); 133 } 134 super.finish(); 135 } 136 } 137