/*
 * 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 android.platform.test.annotations.SecurityTest;

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");
    }

    @SecurityTest(minPatchLevel = "2020-11")
    public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGrantedInPackageInfo");
    }

    @SecurityTest(minPatchLevel = "2020-11")
    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);
    }
}
