/*
 * 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);
    }
}
