blob: a574541ed56ba8f160d51837b4dd11671d8de630 [file] [log] [blame]
/*
* Copyright (C) 2016 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.appsecurity.cts;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IBuildReceiver;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Tests for ephemeral packages.
*/
public class EphemeralTest extends DeviceTestCase
implements IAbiReceiver, IBuildReceiver {
// a normally installed application
private static final String NORMAL_APK = "CtsEphemeralTestsNormalApp.apk";
private static final String NORMAL_PKG = "com.android.cts.normalapp";
// the first ephemerally installed application
private static final String EPHEMERAL_1_APK = "CtsEphemeralTestsEphemeralApp1.apk";
private static final String EPHEMERAL_1_PKG = "com.android.cts.ephemeralapp1";
// the second ephemerally installed application
private static final String EPHEMERAL_2_APK = "CtsEphemeralTestsEphemeralApp2.apk";
private static final String EPHEMERAL_2_PKG = "com.android.cts.ephemeralapp2";
// a normally installed application with implicitly exposed components
private static final String IMPLICIT_APK = "CtsEphemeralTestsImplicitApp.apk";
private static final String IMPLICIT_PKG = "com.android.cts.implicitapp";
// a normally installed application with no exposed components
private static final String UNEXPOSED_APK = "CtsEphemeralTestsUnexposedApp.apk";
private static final String UNEXPOSED_PKG = "com.android.cts.unexposedapp";
private static final String TEST_CLASS = ".ClientTest";
private static final String WEBVIEW_TEST_CLASS = ".WebViewTest";
private static final List<Map<String, String>> EXPECTED_EXPOSED_INTENTS =
new ArrayList<>();
static {
// Framework intents we expect the system to expose to instant applications
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.CHOOSER",
null, null));
// Contact intents we expect the system to expose to instant applications
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.PICK", null, "vnd.android.cursor.dir/contact"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.PICK", null, "vnd.android.cursor.dir/phone_v2"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.PICK", null, "vnd.android.cursor.dir/email_v2"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.PICK", null, "vnd.android.cursor.dir/postal-address_v2"));
// Storage intents we expect the system to expose to instant applications
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.OPEN_DOCUMENT",
"android.intent.category.OPENABLE", "\\*/\\*"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.OPEN_DOCUMENT", null, "\\*/\\*"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.GET_CONTENT",
"android.intent.category.OPENABLE", "\\*/\\*"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.GET_CONTENT", null, "\\*/\\*"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.OPEN_DOCUMENT_TREE", null, null));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.CREATE_DOCUMENT",
"android.intent.category.OPENABLE", "text/plain"));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.intent.action.CREATE_DOCUMENT", null, "text/plain"));
/** Camera intents we expect the system to expose to instant applications */
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.media.action.IMAGE_CAPTURE", null, null));
EXPECTED_EXPOSED_INTENTS.add(makeArgs(
"android.media.action.VIDEO_CAPTURE", null, null));
}
private String mOldVerifierValue;
private IAbi mAbi;
private IBuildInfo mBuildInfo;
@Override
public void setAbi(IAbi abi) {
mAbi = abi;
}
@Override
public void setBuild(IBuildInfo buildInfo) {
mBuildInfo = buildInfo;
}
public void setUp() throws Exception {
super.setUp();
Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildInfo);
uninstallTestPackages();
installTestPackages();
}
public void tearDown() throws Exception {
uninstallTestPackages();
super.tearDown();
}
public void testNormalQuery() throws Exception {
runDeviceTests(NORMAL_PKG, TEST_CLASS, "testQuery");
}
public void testNormalStartNormal() throws Exception {
runDeviceTests(NORMAL_PKG, TEST_CLASS, "testStartNormal");
}
public void testNormalStartEphemeral() throws Exception {
runDeviceTests(NORMAL_PKG, TEST_CLASS, "testStartEphemeral");
}
public void testEphemeralQuery() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testQuery");
}
public void testEphemeralStartNormal() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartNormal");
}
// each connection to an exposed component needs to run in its own test to
// avoid sharing state. once an instant app is exposed to a component, it's
// exposed until the device restarts or the instant app is removed.
public void testEphemeralStartExposed01() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed01");
}
public void testEphemeralStartExposed02() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed02");
}
public void testEphemeralStartExposed03() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed03");
}
public void testEphemeralStartExposed04() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed04");
}
public void testEphemeralStartExposed05() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed05");
}
public void testEphemeralStartExposed06() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed06");
}
public void testEphemeralStartExposed07() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed07");
}
public void testEphemeralStartExposed08() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed08");
}
public void testEphemeralStartExposed09() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed09");
}
public void testEphemeralStartExposed10() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed10");
}
public void testEphemeralStartEphemeral() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartEphemeral");
}
public void testExposedSystemActivities() throws Exception {
for (Map<String, String> testArgs : EXPECTED_EXPOSED_INTENTS) {
final boolean exposed = isIntentExposed(testArgs);
if (exposed) {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testExposedActivity", testArgs);
} else {
CLog.w("Skip intent; " + dumpArgs(testArgs));
}
}
}
public void testBuildSerialUnknown() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testBuildSerialUnknown");
}
public void testPackageInfo() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testPackageInfo");
}
public void testWebViewLoads() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, WEBVIEW_TEST_CLASS, "testWebViewLoads");
}
public void testInstallPermissionNotGranted() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGranted");
}
public void testInstallPermissionGranted() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGranted");
}
public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGrantedInPackageInfo");
}
public void testInstallPermissionGrantedInPackageInfo() throws Exception {
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGrantedInPackageInfo");
}
private static final HashMap<String, String> makeArgs(
String action, String category, String mimeType) {
if (action == null || action.length() == 0) {
fail("action not specified");
}
final HashMap<String, String> testArgs = new HashMap<>();
testArgs.put("action", action);
if (category != null && category.length() > 0) {
testArgs.put("category", category);
}
if (mimeType != null && mimeType.length() > 0) {
testArgs.put("mime_type", mimeType);
}
return testArgs;
}
private boolean isIntentExposed(Map<String, String> testArgs)
throws DeviceNotAvailableException {
final StringBuffer command = new StringBuffer();
command.append("cmd package query-activities");
command.append(" -a ").append(testArgs.get("action"));
if (testArgs.get("category") != null) {
command.append(" -c ").append(testArgs.get("category"));
}
if (testArgs.get("mime_type") != null) {
command.append(" -t ").append(testArgs.get("mime_type"));
}
final String output = getDevice().executeShellCommand(command.toString()).trim();
return !"No activities found".equals(output);
}
private static final String dumpArgs(Map<String, String> testArgs) {
final StringBuffer dump = new StringBuffer();
dump.append("action: ").append(testArgs.get("action"));
if (testArgs.get("category") != null) {
dump.append(", category: ").append(testArgs.get("category"));
}
if (testArgs.get("mime_type") != null) {
dump.append(", type: ").append(testArgs.get("mime_type"));
}
return dump.toString();
}
private void runDeviceTests(String packageName, String testClassName, String testMethodName)
throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
}
private void runDeviceTests(String packageName, String testClassName, String testMethodName,
Map<String, String> testArgs) throws DeviceNotAvailableException {
Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName, testArgs);
}
private void installApp(String apk) throws Exception {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuildInfo);
assertNull(getDevice().installPackage(buildHelper.getTestFile(apk), false));
}
private void installEphemeralApp(String apk) throws Exception {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuildInfo);
assertNull(getDevice().installPackage(buildHelper.getTestFile(apk), false, "--ephemeral"));
}
private void installTestPackages() throws Exception {
installApp(NORMAL_APK);
installApp(UNEXPOSED_APK);
installApp(IMPLICIT_APK);
installEphemeralApp(EPHEMERAL_1_APK);
installEphemeralApp(EPHEMERAL_2_APK);
}
private void uninstallTestPackages() throws Exception {
getDevice().uninstallPackage(NORMAL_PKG);
getDevice().uninstallPackage(UNEXPOSED_PKG);
getDevice().uninstallPackage(IMPLICIT_PKG);
getDevice().uninstallPackage(EPHEMERAL_1_PKG);
getDevice().uninstallPackage(EPHEMERAL_2_PKG);
}
}