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