blob: 2534412f55a46de991b423b6acb6feeeccbc8fa8 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.contentcaptureservice.cts;
import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
import static android.contentcaptureservice.cts.Helper.MY_PACKAGE;
import static android.contentcaptureservice.cts.Helper.resetService;
import static android.contentcaptureservice.cts.Helper.sContext;
import static android.contentcaptureservice.cts.Helper.setService;
import static android.contentcaptureservice.cts.Helper.toSet;
import static android.provider.Settings.Secure.CONTENT_CAPTURE_ENABLED;
import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.contentcaptureservice.cts.CtsContentCaptureService.ServiceWatcher;
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Pair;
import android.view.contentcapture.ContentCaptureManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
import com.android.compatibility.common.util.DeviceConfigStateManager;
import com.android.compatibility.common.util.RequiredServiceRule;
import com.android.compatibility.common.util.SafeCleanerRule;
import com.android.compatibility.common.util.SettingsStateChangerRule;
import com.android.compatibility.common.util.SettingsUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
import java.util.Set;
/**
* Base class for all (or most :-) integration tests in this CTS suite.
*/
@RunWith(AndroidJUnit4.class)
public abstract class AbstractContentCaptureIntegrationTest {
private static final String TAG = AbstractContentCaptureIntegrationTest.class.getSimpleName();
protected static final DeviceConfigStateManager sKillSwitchManager =
new DeviceConfigStateManager(sContext, DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
protected final String mTag = getClass().getSimpleName();
private final RequiredServiceRule mRequiredServiceRule =
new RequiredServiceRule(CONTENT_CAPTURE_MANAGER_SERVICE);
private final DeviceConfigStateChangerRule mVerboseLoggingRule =
new DeviceConfigStateChangerRule(
sContext, DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
Integer.toString(ContentCaptureManager.LOGGING_LEVEL_VERBOSE));
private final ContentCaptureLoggingTestRule mLoggingRule = new ContentCaptureLoggingTestRule();
/**
* Watcher set on {@link #enableService()} and used to wait until it's gone after the test
* finishes.
*/
private ServiceWatcher mServiceWatcher;
protected final SafeCleanerRule mSafeCleanerRule = new SafeCleanerRule()
.setDumper(mLoggingRule)
.add(() -> {
return CtsContentCaptureService.getExceptions();
});
private final TestRule mServiceDisablerRule = (base, description) -> {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} finally {
Log.v(mTag, "@mServiceDisablerRule: safelyDisableService()");
safelyDisableService();
}
}
};
};
private void safelyDisableService() {
try {
resetService();
if (mServiceWatcher != null) {
mServiceWatcher.waitOnDestroy();
}
} catch (Throwable t) {
Log.e(TAG, "error disabling service", t);
}
}
private final DeviceConfigStateChangerRule mKillSwitchKillerRule =
new DeviceConfigStateChangerRule(sKillSwitchManager, "true");
private final SettingsStateChangerRule mFeatureEnablerRule = new SettingsStateChangerRule(
sContext, CONTENT_CAPTURE_ENABLED, "1");
@Rule
public final RuleChain mLookAllTheseRules = RuleChain
// mRequiredServiceRule should be first so the test can be skipped right away
.outerRule(mRequiredServiceRule)
// service must be disable at the last step, otherwise it's contents are not dump in
// case of error
.around(mServiceDisablerRule)
// log everything
.around(mVerboseLoggingRule)
// enable it as soon as possible, as it have to wait for the listener
.around(mKillSwitchKillerRule)
.around(mFeatureEnablerRule)
// mLoggingRule wraps the test but doesn't interfere with it
.around(mLoggingRule)
// mSafeCleanerRule will catch errors
.around(mSafeCleanerRule)
// Finally, let subclasses set their own rule
.around(getMainTestRule());
/**
* Hack to make sure ContentCapture is available for the CTS test package.
*
* <p>It must be set here because when the application starts it queries the server, at which
* point our service is not set yet.
*/
// TODO: remove this hack if we ever split the CTS module in multiple APKs
@BeforeClass
public static void whitelistSelf() {
final ContentCaptureOptions options = ContentCaptureOptions.forWhitelistingItself();
Log.v(TAG, "@BeforeClass: whitelistSelf(): options=" + options);
sContext.getApplicationContext().setContentCaptureOptions(options);
}
@AfterClass
public static void unWhitelistSelf() {
Log.v(TAG, "@afterClass: unWhitelistSelf()");
sContext.getApplicationContext().setContentCaptureOptions(null);
}
@BeforeClass
public static void disableDefaultService() {
Log.v(TAG, "@BeforeClass: disableDefaultService()");
Helper.setDefaultServiceEnabled(false);
}
@AfterClass
public static void enableDefaultService() {
Log.v(TAG, "@AfterClass: enableDefaultService()");
Helper.setDefaultServiceEnabled(true);
}
@Before
public void prepareDevice() throws Exception {
Log.v(mTag, "@Before: prepareDevice()");
// Unlock screen.
runShellCommand("input keyevent KEYCODE_WAKEUP");
// Dismiss keyguard, in case it's set as "Swipe to unlock".
runShellCommand("wm dismiss-keyguard");
// Collapse notifications.
runShellCommand("cmd statusbar collapse");
}
@Before
public void clearState() {
Log.v(mTag, "@Before: clearState()");
CtsContentCaptureService.resetStaticState();
}
@After
public void clearServiceWatcher() {
Log.v(mTag, "@After: clearServiceWatcher()");
CtsContentCaptureService.clearServiceWatcher();
}
@Nullable
public static void setFeatureEnabledBySettings(@Nullable boolean enabled) {
SettingsUtils.syncSet(sContext, CONTENT_CAPTURE_ENABLED, enabled ? "1" : "0");
}
/**
* Sets {@link CtsContentCaptureService} as the service for the current user and waits until
* its created, then whitelist the CTS test package.
*/
public CtsContentCaptureService enableService() throws InterruptedException {
return enableService(toSet(MY_PACKAGE), /* whitelistedComponents= */ null);
}
public CtsContentCaptureService enableService(@Nullable Set<String> whitelistedPackages,
@Nullable Set<ComponentName> whitelistedComponents) throws InterruptedException {
return enableService(new Pair<>(whitelistedPackages, whitelistedComponents));
}
public CtsContentCaptureService enableService(
@Nullable Pair<Set<String>, Set<ComponentName>> whitelist) throws InterruptedException {
if (mServiceWatcher != null) {
throw new IllegalStateException("There Can Be Only One!");
}
mServiceWatcher = CtsContentCaptureService.setServiceWatcher();
setService(CtsContentCaptureService.SERVICE_NAME);
mServiceWatcher.whitelist(whitelist);
return mServiceWatcher.waitOnCreate();
}
/**
* Gets the test-specific {@link Rule}.
*/
@NonNull
protected abstract TestRule getMainTestRule();
}