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 android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE; 19 import static android.contentcaptureservice.cts.Helper.MY_PACKAGE; 20 import static android.contentcaptureservice.cts.Helper.resetService; 21 import static android.contentcaptureservice.cts.Helper.sContext; 22 import static android.contentcaptureservice.cts.Helper.sUserSettings; 23 import static android.contentcaptureservice.cts.Helper.setService; 24 import static android.contentcaptureservice.cts.Helper.toSet; 25 import static android.provider.Settings.Secure.CONTENT_CAPTURE_ENABLED; 26 27 import static com.android.compatibility.common.util.ShellUtils.runShellCommand; 28 29 import android.content.ComponentName; 30 import android.content.ContentCaptureOptions; 31 import android.contentcaptureservice.cts.CtsContentCaptureService.ServiceWatcher; 32 import android.provider.DeviceConfig; 33 import android.util.Log; 34 import android.util.Pair; 35 import android.view.contentcapture.ContentCaptureManager; 36 37 import androidx.annotation.NonNull; 38 import androidx.annotation.Nullable; 39 import androidx.test.ext.junit.runners.AndroidJUnit4; 40 41 import com.android.compatibility.common.util.DeviceConfigStateChangerRule; 42 import com.android.compatibility.common.util.DeviceConfigStateManager; 43 import com.android.compatibility.common.util.RequiredServiceRule; 44 import com.android.compatibility.common.util.SafeCleanerRule; 45 import com.android.compatibility.common.util.SettingsStateChangerRule; 46 47 import org.junit.After; 48 import org.junit.AfterClass; 49 import org.junit.Before; 50 import org.junit.BeforeClass; 51 import org.junit.Rule; 52 import org.junit.rules.RuleChain; 53 import org.junit.rules.TestRule; 54 import org.junit.runner.RunWith; 55 import org.junit.runners.model.Statement; 56 57 import java.util.Set; 58 59 /** 60 * Base class for all (or most :-) integration tests in this CTS suite. 61 */ 62 @RunWith(AndroidJUnit4.class) 63 public abstract class AbstractContentCaptureIntegrationTest { 64 65 private static final String TAG = AbstractContentCaptureIntegrationTest.class.getSimpleName(); 66 67 protected static final DeviceConfigStateManager sKillSwitchManager = 68 new DeviceConfigStateManager(sContext, DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 69 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED); 70 71 protected final String mTag = getClass().getSimpleName(); 72 73 private final RequiredServiceRule mRequiredServiceRule = 74 new RequiredServiceRule(CONTENT_CAPTURE_MANAGER_SERVICE); 75 76 private final DeviceConfigStateChangerRule mVerboseLoggingRule = 77 new DeviceConfigStateChangerRule( 78 sContext, DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 79 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL, 80 Integer.toString(ContentCaptureManager.LOGGING_LEVEL_VERBOSE)); 81 82 private final ContentCaptureLoggingTestRule mLoggingRule = new ContentCaptureLoggingTestRule(); 83 84 /** 85 * Watcher set on {@link #enableService()} and used to wait until it's gone after the test 86 * finishes. 87 */ 88 private ServiceWatcher mServiceWatcher; 89 90 protected final SafeCleanerRule mSafeCleanerRule = new SafeCleanerRule() 91 .setDumper(mLoggingRule) 92 .add(() -> { 93 return CtsContentCaptureService.getExceptions(); 94 }); 95 96 private final TestRule mServiceDisablerRule = (base, description) -> { 97 return new Statement() { 98 @Override 99 public void evaluate() throws Throwable { 100 try { 101 base.evaluate(); 102 } finally { 103 Log.v(mTag, "@mServiceDisablerRule: safelyDisableService()"); 104 safelyDisableService(); 105 } 106 } 107 }; 108 }; 109 safelyDisableService()110 private void safelyDisableService() { 111 try { 112 resetService(); 113 114 if (mServiceWatcher != null) { 115 mServiceWatcher.waitOnDestroy(); 116 } 117 } catch (Throwable t) { 118 Log.e(TAG, "error disabling service", t); 119 } 120 } 121 122 private final DeviceConfigStateChangerRule mKillSwitchKillerRule = 123 new DeviceConfigStateChangerRule(sKillSwitchManager, "true"); 124 125 private final SettingsStateChangerRule mFeatureEnablerRule = new SettingsStateChangerRule( 126 sContext, CONTENT_CAPTURE_ENABLED, "1"); 127 128 @Rule 129 public final RuleChain mLookAllTheseRules = RuleChain 130 // mRequiredServiceRule should be first so the test can be skipped right away 131 .outerRule(mRequiredServiceRule) 132 133 // service must be disable at the last step, otherwise it's contents are not dump in 134 // case of error 135 .around(mServiceDisablerRule) 136 137 // log everything 138 .around(mVerboseLoggingRule) 139 140 // enable it as soon as possible, as it have to wait for the listener 141 .around(mKillSwitchKillerRule) 142 .around(mFeatureEnablerRule) 143 144 // mLoggingRule wraps the test but doesn't interfere with it 145 .around(mLoggingRule) 146 147 // mSafeCleanerRule will catch errors 148 .around(mSafeCleanerRule) 149 150 // Finally, let subclasses set their own rule 151 .around(getMainTestRule()); 152 153 /** 154 * Hack to make sure ContentCapture is available for the CTS test package. 155 * 156 * <p>It must be set here because when the application starts it queries the server, at which 157 * point our service is not set yet. 158 */ 159 // TODO: remove this hack if we ever split the CTS module in multiple APKs 160 @BeforeClass whitelistSelf()161 public static void whitelistSelf() { 162 final ContentCaptureOptions options = ContentCaptureOptions.forWhitelistingItself(); 163 Log.v(TAG, "@BeforeClass: whitelistSelf(): options=" + options); 164 sContext.getApplicationContext().setContentCaptureOptions(options); 165 } 166 167 @AfterClass unWhitelistSelf()168 public static void unWhitelistSelf() { 169 Log.v(TAG, "@afterClass: unWhitelistSelf()"); 170 sContext.getApplicationContext().setContentCaptureOptions(null); 171 } 172 173 @BeforeClass disableDefaultService()174 public static void disableDefaultService() { 175 Log.v(TAG, "@BeforeClass: disableDefaultService()"); 176 Helper.setDefaultServiceEnabled(false); 177 } 178 179 @AfterClass enableDefaultService()180 public static void enableDefaultService() { 181 Log.v(TAG, "@AfterClass: enableDefaultService()"); 182 Helper.setDefaultServiceEnabled(true); 183 } 184 185 @Before prepareDevice()186 public void prepareDevice() throws Exception { 187 Log.v(mTag, "@Before: prepareDevice()"); 188 189 // Unlock screen. 190 runShellCommand("input keyevent KEYCODE_WAKEUP"); 191 192 // Dismiss keyguard, in case it's set as "Swipe to unlock". 193 runShellCommand("wm dismiss-keyguard"); 194 195 // Collapse notifications. 196 runShellCommand("cmd statusbar collapse"); 197 } 198 199 @Before clearState()200 public void clearState() { 201 Log.v(mTag, "@Before: clearState()"); 202 CtsContentCaptureService.resetStaticState(); 203 } 204 205 @After clearServiceWatcher()206 public void clearServiceWatcher() { 207 Log.v(mTag, "@After: clearServiceWatcher()"); 208 CtsContentCaptureService.clearServiceWatcher(); 209 } 210 211 @Nullable setFeatureEnabledBySettings(@ullable boolean enabled)212 public static void setFeatureEnabledBySettings(@Nullable boolean enabled) { 213 sUserSettings.syncSet(CONTENT_CAPTURE_ENABLED, enabled ? "1" : "0"); 214 } 215 216 /** 217 * Sets {@link CtsContentCaptureService} as the service for the current user and waits until 218 * its created, then allowlist the CTS test package. 219 */ enableService()220 public CtsContentCaptureService enableService() throws InterruptedException { 221 return enableService(toSet(MY_PACKAGE), /* whitelistedComponents= */ null); 222 } 223 enableService(@ullable Set<String> whitelistedPackages, @Nullable Set<ComponentName> whitelistedComponents)224 public CtsContentCaptureService enableService(@Nullable Set<String> whitelistedPackages, 225 @Nullable Set<ComponentName> whitelistedComponents) throws InterruptedException { 226 return enableService(new Pair<>(whitelistedPackages, whitelistedComponents)); 227 } 228 enableService( @ullable Pair<Set<String>, Set<ComponentName>> whitelist)229 public CtsContentCaptureService enableService( 230 @Nullable Pair<Set<String>, Set<ComponentName>> whitelist) throws InterruptedException { 231 if (mServiceWatcher != null) { 232 throw new IllegalStateException("There Can Be Only One!"); 233 } 234 mServiceWatcher = CtsContentCaptureService.setServiceWatcher(); 235 setService(CtsContentCaptureService.SERVICE_NAME); 236 237 mServiceWatcher.whitelist(whitelist); 238 239 return mServiceWatcher.waitOnCreate(); 240 } 241 242 /** 243 * Gets the test-specific {@link Rule}. 244 */ 245 @NonNull getMainTestRule()246 protected abstract TestRule getMainTestRule(); 247 } 248