1 /* 2 * Copyright (C) 2018 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 package android.contentcaptureservice.cts; 17 18 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 19 20 import static com.android.compatibility.common.util.ShellUtils.runShellCommand; 21 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.res.Resources; 25 import android.os.SystemClock; 26 import android.util.ArraySet; 27 import android.util.Log; 28 import android.view.View; 29 import android.view.contentcapture.ContentCaptureSession; 30 import android.widget.TextView; 31 32 import androidx.annotation.NonNull; 33 import androidx.annotation.Nullable; 34 35 import com.android.compatibility.common.util.Timeout; 36 37 import java.io.File; 38 import java.io.IOException; 39 import java.nio.file.Files; 40 import java.nio.file.Paths; 41 import java.util.Set; 42 import java.util.concurrent.Callable; 43 import java.util.concurrent.CountDownLatch; 44 import java.util.concurrent.TimeUnit; 45 46 /** 47 * Helper for common funcionalities. 48 */ 49 public final class Helper { 50 51 public static final String TAG = "ContentCaptureTest"; 52 53 public static final long GENERIC_TIMEOUT_MS = 10_000; 54 55 public static final String MY_PACKAGE = "android.contentcaptureservice.cts"; 56 public static final String OTHER_PACKAGE = "NOT.android.contentcaptureservice.cts"; 57 58 public static final Set<String> NO_PACKAGES = null; 59 public static final Set<ComponentName> NO_ACTIVITIES = null; 60 61 public static final long MY_EPOCH = SystemClock.uptimeMillis(); 62 63 public static final String RESOURCE_STRING_SERVICE_NAME = "config_defaultContentCaptureService"; 64 65 public static final Context sContext = getInstrumentation().getTargetContext(); 66 67 private static final Timeout MY_TIMEOUT = new Timeout("MY_TIMEOUT", GENERIC_TIMEOUT_MS, 2F, 68 GENERIC_TIMEOUT_MS); 69 70 /** 71 * Awaits for a latch to be counted down. 72 */ await(@onNull CountDownLatch latch, @NonNull String fmt, @Nullable Object... args)73 public static void await(@NonNull CountDownLatch latch, @NonNull String fmt, 74 @Nullable Object... args) 75 throws InterruptedException { 76 final boolean called = latch.await(GENERIC_TIMEOUT_MS, TimeUnit.MILLISECONDS); 77 if (!called) { 78 throw new IllegalStateException(String.format(fmt, args) 79 + " in " + GENERIC_TIMEOUT_MS + "ms"); 80 } 81 } 82 83 /** 84 * Sets the content capture service. 85 */ setService(@onNull String service)86 public static void setService(@NonNull String service) { 87 Log.d(TAG, "Setting service to " + service); 88 // TODO(b/123540602): use @TestingAPI to get max duration constant 89 runShellCommand("cmd content_capture set temporary-service 0 " + service + " 12000"); 90 } 91 92 /** 93 * Resets the content capture service. 94 */ resetService()95 public static void resetService() { 96 Log.d(TAG, "Resetting back to default service"); 97 runShellCommand("cmd content_capture set temporary-service 0"); 98 } 99 100 /** 101 * Enables / disables the default service. 102 */ setDefaultServiceEnabled(boolean enabled)103 public static void setDefaultServiceEnabled(boolean enabled) { 104 Log.d(TAG, "setDefaultServiceEnabled(): " + enabled); 105 runShellCommand("cmd content_capture set default-service-enabled 0 %s", 106 Boolean.toString(enabled)); 107 } 108 109 /** 110 * Gets the component name for a given class. 111 */ componentNameFor(@onNull Class<?> clazz)112 public static ComponentName componentNameFor(@NonNull Class<?> clazz) { 113 return new ComponentName(MY_PACKAGE, clazz.getName()); 114 } 115 116 /** 117 * Creates a view that can be added to a parent and is important for content capture 118 */ newImportantView(@onNull Context context, @NonNull String text)119 public static TextView newImportantView(@NonNull Context context, @NonNull String text) { 120 final TextView child = new TextView(context); 121 child.setText(text); 122 child.setImportantForContentCapture(View.IMPORTANT_FOR_CONTENT_CAPTURE_YES); 123 Log.v(TAG, "newImportantView(text=" + text + ", id=" + child.getAutofillId() + ")"); 124 return child; 125 } 126 127 /** 128 * Creates a view that can be added to a parent and is important for content capture 129 */ newImportantView(@onNull Context context, @NonNull ContentCaptureSession session, @NonNull String text)130 public static TextView newImportantView(@NonNull Context context, 131 @NonNull ContentCaptureSession session, @NonNull String text) { 132 final TextView child = newImportantView(context, text); 133 child.setContentCaptureSession(session); 134 return child; 135 } 136 137 /** 138 * Gets a string from the Android resources. 139 */ getInternalString(@onNull String id)140 public static String getInternalString(@NonNull String id) { 141 final Resources resources = sContext.getResources(); 142 final int stringId = resources.getIdentifier(id, "string", "android"); 143 return resources.getString(stringId); 144 } 145 146 /** 147 * Runs an {@code assertion}, retrying until {@link #MY_TIMEOUT} is reached. 148 */ eventually(@onNull String description, @NonNull Callable<T> assertion)149 public static <T> T eventually(@NonNull String description, @NonNull Callable<T> assertion) 150 throws Exception { 151 return MY_TIMEOUT.run(description, assertion); 152 } 153 154 /** 155 * Creates a Set with the given objects. 156 */ toSet(@uppressWarnings"unchecked") @ullable T... objs)157 public static <T> ArraySet<T> toSet(@SuppressWarnings("unchecked") @Nullable T... objs) { 158 final ArraySet<T> set = new ArraySet<>(); 159 if (objs != null) { 160 for (int i = 0; i < objs.length; i++) { 161 final T t = objs[i]; 162 set.add(t); 163 } 164 } 165 return set; 166 } 167 168 /** 169 * Gets the content of the given file. 170 */ read(@onNull File file)171 public static String read(@NonNull File file) throws IOException { 172 Log.d(TAG, "Reading " + file); 173 final byte[] bytes = Files.readAllBytes(Paths.get(file.getAbsolutePath())); 174 return bytes == null ? null : new String(bytes); 175 } 176 Helper()177 private Helper() { 178 throw new UnsupportedOperationException("contain static methods only"); 179 } 180 } 181