/*
 * Copyright (C) 2015 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 com.android.cts.devicepolicy;

import android.platform.test.annotations.RequiresDevice;

import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.log.LogUtil.CLog;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Set of tests for use cases that apply to profile and device owner.
 * This class is the base class of MixedProfileOwnerTest, MixedDeviceOwnerTest and
 * MixedManagedProfileOwnerTest and is abstract to avoid running spurious tests.
 *
 * NOTE: Not all tests are executed in the subclasses.  Sometimes, if a test is not applicable to
 * a subclass, they override it with an empty method.
 */
public abstract class DeviceAndProfileOwnerTest extends BaseDevicePolicyTest {

    protected static final String DEVICE_ADMIN_PKG = "com.android.cts.deviceandprofileowner";
    protected static final String DEVICE_ADMIN_APK = "CtsDeviceAndProfileOwnerApp.apk";
    protected static final String ADMIN_RECEIVER_TEST_CLASS
            = ".BaseDeviceAdminTest$BasicAdminReceiver";

    private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
    private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";

    private static final String INTENT_SENDER_PKG = "com.android.cts.intent.sender";
    private static final String INTENT_SENDER_APK = "CtsIntentSenderApp.apk";

    private static final String PERMISSIONS_APP_PKG = "com.android.cts.permissionapp";
    private static final String PERMISSIONS_APP_APK = "CtsPermissionApp.apk";

    private static final String SIMPLE_PRE_M_APP_PKG = "com.android.cts.launcherapps.simplepremapp";
    private static final String SIMPLE_PRE_M_APP_APK = "CtsSimplePreMApp.apk";

    private static final String APP_RESTRICTIONS_TARGET_APP_PKG
            = "com.android.cts.apprestrictions.targetapp";
    private static final String APP_RESTRICTIONS_TARGET_APP_APK = "CtsAppRestrictionsTargetApp.apk";

    private static final String CERT_INSTALLER_PKG = "com.android.cts.certinstaller";
    private static final String CERT_INSTALLER_APK = "CtsCertInstallerApp.apk";

    private static final String DELEGATE_APP_PKG = "com.android.cts.delegate";
    private static final String DELEGATE_APP_APK = "CtsDelegateApp.apk";
    private static final String DELEGATION_CERT_INSTALL = "delegation-cert-install";
    private static final String DELEGATION_APP_RESTRICTIONS = "delegation-app-restrictions";
    private static final String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall";
    private static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
    private static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
    private static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";

    private static final String TEST_APP_APK = "CtsSimpleApp.apk";
    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
    private static final String TEST_APP_LOCATION = "/data/local/tmp/";

    private static final String PACKAGE_INSTALLER_PKG = "com.android.cts.packageinstaller";
    private static final String PACKAGE_INSTALLER_APK = "CtsPackageInstallerApp.apk";

    private static final String ACCOUNT_MANAGEMENT_PKG
            = "com.android.cts.devicepolicy.accountmanagement";
    private static final String ACCOUNT_MANAGEMENT_APK = "CtsAccountManagementDevicePolicyApp.apk";

    private static final String VPN_APP_PKG = "com.android.cts.vpnfirewall";
    private static final String VPN_APP_APK = "CtsVpnFirewallApp.apk";

    private static final String COMMAND_BLOCK_ACCOUNT_TYPE = "block-accounttype";
    private static final String COMMAND_UNBLOCK_ACCOUNT_TYPE = "unblock-accounttype";

    private static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
    private static final String DISALLOW_REMOVE_USER = "no_remove_user";
    private static final String ACCOUNT_TYPE
            = "com.android.cts.devicepolicy.accountmanagement.account.type";

    private static final String CUSTOMIZATION_APP_PKG = "com.android.cts.customizationapp";
    private static final String CUSTOMIZATION_APP_APK = "CtsCustomizationApp.apk";

    private static final String AUTOFILL_APP_PKG = "com.android.cts.devicepolicy.autofillapp";
    private static final String AUTOFILL_APP_APK = "CtsDevicePolicyAutofillApp.apk";

    protected static final String ASSIST_APP_PKG = "com.android.cts.devicepolicy.assistapp";
    protected static final String ASSIST_APP_APK = "CtsDevicePolicyAssistApp.apk";

    private static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES
            = "enabled_notification_policy_access_packages";

    protected static final String ASSIST_INTERACTION_SERVICE =
            ASSIST_APP_PKG + "/.MyInteractionService";

    // ID of the user all tests are run as. For device owner this will be the primary user, for
    // profile owner it is the user id of the created profile.
    protected int mUserId;

    @Override
    protected void tearDown() throws Exception {
        if (mHasFeature) {
            getDevice().uninstallPackage(DEVICE_ADMIN_PKG);
            getDevice().uninstallPackage(PERMISSIONS_APP_PKG);
            getDevice().uninstallPackage(SIMPLE_PRE_M_APP_PKG);
            getDevice().uninstallPackage(APP_RESTRICTIONS_TARGET_APP_PKG);
            getDevice().uninstallPackage(CERT_INSTALLER_PKG);
            getDevice().uninstallPackage(DELEGATE_APP_PKG);
            getDevice().uninstallPackage(ACCOUNT_MANAGEMENT_PKG);
            getDevice().uninstallPackage(VPN_APP_PKG);
            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
            getDevice().uninstallPackage(INTENT_SENDER_PKG);
            getDevice().uninstallPackage(CUSTOMIZATION_APP_PKG);
            getDevice().uninstallPackage(AUTOFILL_APP_APK);
            getDevice().uninstallPackage(TEST_APP_PKG);

            // Press the HOME key to close any alart dialog that may be shown.
            getDevice().executeShellCommand("input keyevent 3");
        }
        super.tearDown();
    }

    public void testCaCertManagement() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestClass(".CaCertManagementTest");
    }

    public void testApplicationRestrictions() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(DELEGATE_APP_APK, mUserId);
        installAppAsUser(APP_RESTRICTIONS_TARGET_APP_APK, mUserId);

        try {
            // Only the DPC can manage app restrictions by default.
            executeDeviceTestClass(".ApplicationRestrictionsTest");
            executeAppRestrictionsManagingPackageTest("testCannotAccessApis");

            // Letting the DELEGATE_APP_PKG manage app restrictions too.
            changeApplicationRestrictionsManagingPackage(DELEGATE_APP_PKG);
            executeAppRestrictionsManagingPackageTest("testCanAccessApis");
            runDeviceTestsAsUser(DELEGATE_APP_PKG, ".GeneralDelegateTest",
                    "testSettingAdminComponentNameThrowsException", mUserId);

            // The DPC should still be able to manage app restrictions normally.
            executeDeviceTestClass(".ApplicationRestrictionsTest");

            // The app shouldn't be able to manage app restrictions for other users.
            int parentUserId = getPrimaryUser();
            if (parentUserId != mUserId) {
                installAppAsUser(DELEGATE_APP_APK, parentUserId);
                installAppAsUser(APP_RESTRICTIONS_TARGET_APP_APK, parentUserId);
                runDeviceTestsAsUser(DELEGATE_APP_PKG, ".AppRestrictionsDelegateTest",
                        "testCannotAccessApis", parentUserId);
            }

            // Revoking the permission for DELEGAYE_APP_PKG to manage restrictions.
            changeApplicationRestrictionsManagingPackage(null);
            executeAppRestrictionsManagingPackageTest("testCannotAccessApis");

            // The DPC should still be able to manage app restrictions normally.
            executeDeviceTestClass(".ApplicationRestrictionsTest");
        } finally {
            changeApplicationRestrictionsManagingPackage(null);
        }
    }

    public void testDelegation() throws Exception {
        if (!mHasFeature) {
            return;
        }

        final String delegationTests[] = {
            ".AppRestrictionsDelegateTest",
            ".CertInstallDelegateTest",
            ".BlockUninstallDelegateTest",
            ".PermissionGrantDelegateTest",
            ".PackageAccessDelegateTest",
            ".EnableSystemAppDelegateTest"
        };

        // Set a device lockscreen password (precondition for installing private key pairs).
        changeUserCredential("1234", null, mPrimaryUserId);

        // Install relevant apps.
        installAppAsUser(DELEGATE_APP_APK, mUserId);
        installAppAsUser(TEST_APP_APK, mUserId);
        installAppAsUser(APP_RESTRICTIONS_TARGET_APP_APK, mUserId);

        try {
            // APIs are not accessible by default.
            executeDelegationTests(delegationTests, false /* negative result */);

            // Granting the appropriate delegation scopes makes APIs accessible.
            setDelegatedScopes(DELEGATE_APP_PKG, Arrays.asList(
                    DELEGATION_APP_RESTRICTIONS,
                    DELEGATION_CERT_INSTALL,
                    DELEGATION_BLOCK_UNINSTALL,
                    DELEGATION_PERMISSION_GRANT,
                    DELEGATION_PACKAGE_ACCESS,
                    DELEGATION_ENABLE_SYSTEM_APP));
            runDeviceTestsAsUser(DELEGATE_APP_PKG, ".GeneralDelegateTest", mUserId);
            executeDelegationTests(delegationTests, true /* positive result */);

            // APIs are not accessible after revoking delegations.
            setDelegatedScopes(DELEGATE_APP_PKG, null);
            executeDelegationTests(delegationTests, false /* negative result */);

            // Additional delegation tests.
            executeDeviceTestClass(".DelegationTest");

        } finally {
            // Clear lockscreen password previously set for installing private key pairs.
            changeUserCredential(null, "1234", mPrimaryUserId);
            // Remove any remaining delegations.
            setDelegatedScopes(DELEGATE_APP_PKG, null);
        }
    }

    public void testPermissionGrant() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionGrantState");
    }

    /**
     * Require a device for tests that use the network stack. Headless Androids running in
     * data centres might need their network rules un-tampered-with in order to keep the ADB / VNC
     * connection alive.
     *
     * This is only a problem on device owner / profile owner running on USER_SYSTEM, because
     * network rules for this user will affect UID 0.
     */
    @RequiresDevice
    public void testAlwaysOnVpn() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppAsUser(VPN_APP_APK, mUserId);
        executeDeviceTestClass(".AlwaysOnVpnTest");
    }

    @RequiresDevice
    public void testAlwaysOnVpnLockDown() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(VPN_APP_APK, mUserId);
        try {
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testAlwaysOnSet");
            forceStopPackageForUser(VPN_APP_PKG, mUserId);
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testNetworkBlocked");
        } finally {
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testCleanup");
        }
    }

    @RequiresDevice
    public void testAlwaysOnVpnPackageUninstalled() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(VPN_APP_APK, mUserId);
        try {
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testAlwaysOnSet");
            getDevice().uninstallPackage(VPN_APP_PKG);
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testAlwaysOnVpnDisabled");
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testSetNonExistingPackage");
        } finally {
            executeDeviceTestMethod(".AlwaysOnVpnMultiStageTest", "testCleanup");
        }
    }

    public void testPermissionPolicy() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionPolicy");
    }

    public void testPermissionMixedPolicies() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionMixedPolicies");
    }

    // Test flakey; suppressed.
//    public void testPermissionPrompts() throws Exception {
//        if (!mHasFeature) {
//            return;
//        }
//        installAppPermissionAppAsUser();
//        executeDeviceTestMethod(".PermissionsTest", "testPermissionPrompts");
//    }

    public void testPermissionAppUpdate() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_setDeniedState");
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkDenied");
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkDenied");

        assertNull(getDevice().uninstallPackage(PERMISSIONS_APP_PKG));
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_setGrantedState");
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkGranted");
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkGranted");

        assertNull(getDevice().uninstallPackage(PERMISSIONS_APP_PKG));
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_setAutoDeniedPolicy");
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkDenied");
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkDenied");

        assertNull(getDevice().uninstallPackage(PERMISSIONS_APP_PKG));
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_setAutoGrantedPolicy");
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkGranted");
        installAppPermissionAppAsUser();
        executeDeviceTestMethod(".PermissionsTest", "testPermissionUpdate_checkGranted");
    }

    public void testPermissionGrantPreMApp() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppAsUser(SIMPLE_PRE_M_APP_APK, mUserId);
        executeDeviceTestMethod(".PermissionsTest", "testPermissionGrantStatePreMApp");
    }

    public void testPersistentIntentResolving() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestClass(".PersistentIntentResolvingTest");
    }

    public void testScreenCaptureDisabled() throws Exception {
        if (!mHasFeature) {
            return;
        }
        // We need to ensure that the policy is deactivated for the device owner case, so making
        // sure the second test is run even if the first one fails
        try {
            setScreenCaptureDisabled(mUserId, true);
        } finally {
            setScreenCaptureDisabled(mUserId, false);
        }
    }

    public void testScreenCaptureDisabled_assist() throws Exception {
        if (!mHasFeature) {
            return;
        }
        try {
            // Install and enable assistant, notice that profile can't have assistant.
            installAppAsUser(ASSIST_APP_APK, mPrimaryUserId);
            setVoiceInteractionService(ASSIST_INTERACTION_SERVICE);
            setScreenCaptureDisabled_assist(mUserId, true /* disabled */);
        } finally {
            setScreenCaptureDisabled_assist(mUserId, false /* disabled */);
            clearVoiceInteractionService();
        }
    }

    public void testSupportMessage() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestClass(".SupportMessageTest");
    }

    public void testApplicationHidden() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppPermissionAppAsUser();
        executeDeviceTestClass(".ApplicationHiddenTest");
    }

    public void testAccountManagement_deviceAndProfileOwnerAlwaysAllowed() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
        executeDeviceTestClass(".DpcAllowedAccountManagementTest");
    }

    public void testAccountManagement_userRestrictionAddAccount() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
        try {
            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, true, mUserId);
            executeAccountTest("testAddAccount_blocked");
        } finally {
            // Ensure we clear the user restriction
            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, false, mUserId);
        }
        executeAccountTest("testAddAccount_allowed");
    }

    public void testAccountManagement_userRestrictionRemoveAccount() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
        try {
            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, true, mUserId);
            executeAccountTest("testRemoveAccount_blocked");
        } finally {
            // Ensure we clear the user restriction
            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, false, mUserId);
        }
        executeAccountTest("testRemoveAccount_allowed");
    }

    public void testAccountManagement_disabledAddAccount() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
        try {
            changeAccountManagement(COMMAND_BLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
            executeAccountTest("testAddAccount_blocked");
        } finally {
            // Ensure we remove account management policies
            changeAccountManagement(COMMAND_UNBLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
        }
        executeAccountTest("testAddAccount_allowed");
    }

    public void testAccountManagement_disabledRemoveAccount() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
        try {
            changeAccountManagement(COMMAND_BLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
            executeAccountTest("testRemoveAccount_blocked");
        } finally {
            // Ensure we remove account management policies
            changeAccountManagement(COMMAND_UNBLOCK_ACCOUNT_TYPE, ACCOUNT_TYPE, mUserId);
        }
        executeAccountTest("testRemoveAccount_allowed");
    }

    public void testDelegatedCertInstaller() throws Exception {
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(CERT_INSTALLER_APK, mUserId);

        boolean isManagedProfile = (mPrimaryUserId != mUserId);

        try {
            // Set a non-empty device lockscreen password, which is a precondition for installing
            // private key pairs.
            changeUserCredential("1234", null, mUserId);

            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".DelegatedCertInstallerTest", mUserId);
        } finally {
            if (!isManagedProfile) {
                // Skip managed profile as dpm doesn't allow clear password
                changeUserCredential(null, "1234", mUserId);
            }
        }
    }

    // Sets restrictions and launches non-admin app, that tries to set wallpaper.
    // Non-admin apps must not violate any user restriction.
    public void testSetWallpaper_disallowed() throws Exception {
        // UserManager.DISALLOW_SET_WALLPAPER
        final String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
        if (!mHasFeature) {
            return;
        }

        installAppAsUser(CUSTOMIZATION_APP_APK, mUserId);
        try {
            changeUserRestrictionOrFail(DISALLOW_SET_WALLPAPER, true, mUserId);
            runDeviceTestsAsUser(CUSTOMIZATION_APP_PKG, ".CustomizationTest",
                "testSetWallpaper_disallowed", mUserId);
        } finally {
            changeUserRestrictionOrFail(DISALLOW_SET_WALLPAPER, false, mUserId);
        }
    }

    // Runs test with admin privileges. The test methods set all the tested restrictions
    // inside. But these restrictions must have no effect on the device/profile owner behavior.
    public void testDisallowSetWallpaper_allowed() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestMethod(".CustomizationRestrictionsTest",
                "testDisallowSetWallpaper_allowed");
    }

    public void testDisallowSetUserIcon_allowed() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestMethod(".CustomizationRestrictionsTest",
                "testDisallowSetUserIcon_allowed");
    }

    public void testDisallowAutofill_allowed() throws Exception {
        if (!mHasFeature) {
            return;
        }
        boolean mHasAutofill = hasDeviceFeature("android.software.autofill");
        if (!mHasAutofill) {
          return;
        }
        installAppAsUser(AUTOFILL_APP_APK, mUserId);

        executeDeviceTestMethod(".AutofillRestrictionsTest",
                "testDisallowAutofill_allowed");
    }

    public void testPackageInstallUserRestrictions() throws Exception {
        if (!mHasFeature) {
            return;
        }
        boolean mIsWatch = hasDeviceFeature("android.hardware.type.watch");
        if (mIsWatch) {
            return;
        }
        // UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
        final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
        final String PACKAGE_VERIFIER_USER_CONSENT_SETTING = "package_verifier_user_consent";
        final String PACKAGE_VERIFIER_ENABLE_SETTING = "package_verifier_enable";
        final String SECURE_SETTING_CATEGORY = "secure";
        final String GLOBAL_SETTING_CATEGORY = "global";
        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
        final File apk = buildHelper.getTestFile(TEST_APP_APK);
        String packageVerifierEnableSetting = null;
        String packageVerifierUserConsentSetting = null;
        try {
            // Install the test and prepare the test apk.
            installAppAsUser(PACKAGE_INSTALLER_APK, mUserId);
            assertTrue(getDevice().pushFile(apk, TEST_APP_LOCATION + apk.getName()));
            setInstallPackageAppOps(PACKAGE_INSTALLER_PKG, true, mUserId);

            // Add restrictions and test if we can install the apk.
            getDevice().uninstallPackage(TEST_APP_PKG);
            changeUserRestrictionOrFail(DISALLOW_INSTALL_UNKNOWN_SOURCES, true, mUserId);
            runDeviceTestsAsUser(PACKAGE_INSTALLER_PKG, ".ManualPackageInstallTest",
                    "testManualInstallBlocked", mUserId);

            // Clear restrictions and test if we can install the apk.
            changeUserRestrictionOrFail(DISALLOW_INSTALL_UNKNOWN_SOURCES, false, mUserId);

            // Disable verifier.
            packageVerifierUserConsentSetting = getSettings(SECURE_SETTING_CATEGORY,
                    PACKAGE_VERIFIER_USER_CONSENT_SETTING, mUserId);
            packageVerifierEnableSetting = getSettings(GLOBAL_SETTING_CATEGORY,
                    PACKAGE_VERIFIER_ENABLE_SETTING, mUserId);

            putSettings(SECURE_SETTING_CATEGORY, PACKAGE_VERIFIER_USER_CONSENT_SETTING, "-1",
                    mUserId);
            putSettings(GLOBAL_SETTING_CATEGORY, PACKAGE_VERIFIER_ENABLE_SETTING, "0", mUserId);
            // Skip verifying above setting values as some of them may be overrided.
            runDeviceTestsAsUser(PACKAGE_INSTALLER_PKG, ".ManualPackageInstallTest",
                    "testManualInstallSucceeded", mUserId);
        } finally {
            setInstallPackageAppOps(PACKAGE_INSTALLER_PKG, false, mUserId);
            String command = "rm " + TEST_APP_LOCATION + apk.getName();
            getDevice().executeShellCommand(command);
            getDevice().uninstallPackage(TEST_APP_PKG);
            getDevice().uninstallPackage(PACKAGE_INSTALLER_PKG);
            if (packageVerifierEnableSetting != null) {
                putSettings(GLOBAL_SETTING_CATEGORY, PACKAGE_VERIFIER_ENABLE_SETTING,
                        packageVerifierEnableSetting, mUserId);
            }
            if (packageVerifierUserConsentSetting != null) {
                putSettings(SECURE_SETTING_CATEGORY, PACKAGE_VERIFIER_USER_CONSENT_SETTING,
                        packageVerifierUserConsentSetting, mUserId);
            }
        }
    }

    public void testAudioRestriction() throws Exception {
        if (!mHasFeature) {
            return;
        }
        // This package may need to toggle zen mode for this test, so allow it to do so.
        allowNotificationPolicyAccess(DEVICE_ADMIN_PKG, mUserId);
        try {
            executeDeviceTestClass(".AudioRestrictionTest");
        } finally {
            disallowNotificationPolicyAccess(DEVICE_ADMIN_PKG, mUserId);
        }
    }

    public void testSuspendPackage() throws Exception {
        if (!mHasFeature) {
            return;
        }
        installAppAsUser(INTENT_SENDER_APK, mUserId);
        installAppAsUser(INTENT_RECEIVER_APK, mUserId);
        // Suspend a testing package.
        executeDeviceTestMethod(".SuspendPackageTest", "testSetPackagesSuspended");
        // Verify that the package is suspended.
        executeSuspendPackageTestMethod("testPackageSuspended");
        // Undo the suspend.
        executeDeviceTestMethod(".SuspendPackageTest", "testSetPackagesNotSuspended");
        // Verify that the package is not suspended.
        executeSuspendPackageTestMethod("testPackageNotSuspended");
        // Verify we cannot suspend not suspendable packages.
        executeDeviceTestMethod(".SuspendPackageTest", "testSuspendNotSuspendablePackages");
    }

    public void testTrustAgentInfo() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestClass(".TrustAgentInfoTest");
    }

    public void testCannotRemoveUserIfRestrictionSet() throws Exception {
        // Outside of the primary user, setting DISALLOW_REMOVE_USER would not work.
        if (!mHasFeature || !canCreateAdditionalUsers(1) || mUserId != getPrimaryUser()) {
            return;
        }
        final int userId = createUser();
        try {
            changeUserRestrictionOrFail(DISALLOW_REMOVE_USER, true, mUserId);
            assertFalse(getDevice().removeUser(userId));
        } finally {
            changeUserRestrictionOrFail(DISALLOW_REMOVE_USER, false, mUserId);
            assertTrue(getDevice().removeUser(userId));
        }
    }

    public void testCannotEnableOrDisableDeviceOwnerOrProfileOwner() throws Exception {
        if (!mHasFeature) {
            return;
        }
        // Try to disable a component in device owner/ profile owner.
        String result = disableComponentOrPackage(
                mUserId, DEVICE_ADMIN_PKG + "/.SetPolicyActivity");
        assertTrue("Should throw SecurityException",
                result.contains("java.lang.SecurityException"));
        // Try to disable the device owner/ profile owner package.
        result = disableComponentOrPackage(mUserId, DEVICE_ADMIN_PKG);
        assertTrue("Should throw SecurityException",
                result.contains("java.lang.SecurityException"));
        // Try to enable a component in device owner/ profile owner.
        result = enableComponentOrPackage(
                mUserId, DEVICE_ADMIN_PKG + "/.SetPolicyActivity");
        assertTrue("Should throw SecurityException",
                result.contains("java.lang.SecurityException"));
        // Try to enable the device owner/ profile owner package.
        result = enableComponentOrPackage(mUserId, DEVICE_ADMIN_PKG);
        assertTrue("Should throw SecurityException",
                result.contains("java.lang.SecurityException"));

    }

    public void testRequiredStrongAuthTimeout() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestClass(".RequiredStrongAuthTimeoutTest");
    }

    public void testCreateAdminSupportIntent() throws Exception {
        if (!mHasFeature) {
            return;
        }
        executeDeviceTestClass(".PolicyTransparencyTest");
    }

    public void testResetPasswordWithToken() throws Exception {
        if (!mHasFeature) {
            return;
        }
        // If ResetPasswordWithTokenTest for managed profile is executed before device owner and
        // primary user profile owner tests, password reset token would have been disabled for
        // the primary user, so executing ResetPasswordWithTokenTest on user 0 would fail. We allow
        // this and do not fail the test in this case.
        // This is the default test for MixedDeviceOwnerTest and MixedProfileOwnerTest,
        // MixedManagedProfileOwnerTest overrides this method to execute the same test more strictly
        // without allowing failures.
        executeDeviceTestMethod(".ResetPasswordWithTokenTest", "testResetPasswordWithTokenMayFail");
    }

    protected void executeDeviceTestClass(String className) throws Exception {
        runDeviceTestsAsUser(DEVICE_ADMIN_PKG, className, mUserId);
    }

    protected void executeDeviceTestMethod(String className, String testName) throws Exception {
        runDeviceTestsAsUser(DEVICE_ADMIN_PKG, className, testName, mUserId);
    }

    private void installAppPermissionAppAsUser()
            throws FileNotFoundException, DeviceNotAvailableException {
        installAppAsUser(PERMISSIONS_APP_APK, false, mUserId);
    }

    private void executeSuspendPackageTestMethod(String testName) throws Exception {
        runDeviceTestsAsUser(INTENT_SENDER_PKG, ".SuspendPackageTest",
                testName, mUserId);
    }

    private void executeAccountTest(String testName) throws DeviceNotAvailableException {
        runDeviceTestsAsUser(ACCOUNT_MANAGEMENT_PKG, ".AccountManagementTest",
                testName, mUserId);
        // Send a home intent to dismiss an error dialog.
        String command = "am start -a android.intent.action.MAIN"
                + " -c android.intent.category.HOME";
        CLog.i("Output for command " + command + ": " + getDevice().executeShellCommand(command));
    }

    private void executeAppRestrictionsManagingPackageTest(String testName) throws Exception {
        runDeviceTestsAsUser(DELEGATE_APP_PKG,
                ".AppRestrictionsDelegateTest", testName, mUserId);
    }

    private void executeDelegationTests(String[] delegationTests, boolean positive)
            throws Exception {
        for (String delegationTestClass : delegationTests) {
            runDeviceTestsAsUser(DELEGATE_APP_PKG, delegationTestClass,
                positive ? "testCanAccessApis" : "testCannotAccessApis", mUserId);
        }
    }

    private void changeUserRestrictionOrFail(String key, boolean value, int userId)
            throws DeviceNotAvailableException {
        changeUserRestrictionOrFail(key, value, userId, DEVICE_ADMIN_PKG);
    }

    private void changeAccountManagement(String command, String accountType, int userId)
            throws DeviceNotAvailableException {
        changePolicyOrFail(command, "--es extra-account-type " + accountType, userId);
    }

    private void changeApplicationRestrictionsManagingPackage(String packageName)
            throws DeviceNotAvailableException {
        String packageNameExtra = (packageName != null)
                ? "--es extra-package-name " + packageName : "";
        changePolicyOrFail("set-app-restrictions-manager", packageNameExtra, mUserId);
    }

    private void setDelegatedScopes(String packageName, List<String> scopes)
            throws DeviceNotAvailableException {
        final String packageNameExtra = "--es extra-package-name " + packageName;
        String scopesExtra = "";
        if (scopes != null && scopes.size() > 0) {
            scopesExtra = "--esa extra-scopes-list " + scopes.get(0);
            for (int i = 1; i < scopes.size(); ++i) {
                scopesExtra += "," + scopes.get(i);
            }
        }
        final String extras = packageNameExtra + " " + scopesExtra;

        changePolicyOrFail("set-delegated-scopes", extras, mUserId);
    }

    private void setInstallPackageAppOps(String packageName, boolean allowed, int userId)
            throws DeviceNotAvailableException {
        String command = "appops set --user " + userId + " " + packageName + " " +
                "REQUEST_INSTALL_PACKAGES "
                + (allowed ? "allow" : "default");
        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
    }

    private void changePolicyOrFail(String command, String extras, int userId)
            throws DeviceNotAvailableException {
        changePolicyOrFail(command, extras, userId, DEVICE_ADMIN_PKG);
    }

    /**
     * Start SimpleActivity synchronously in a particular user.
     */
    protected void startSimpleActivityAsUser(int userId) throws Exception {
        installAppAsUser(TEST_APP_APK, userId);
        wakeupAndDismissKeyguard();
        String command = "am start -W --user " + userId + " " + TEST_APP_PKG + "/"
                + TEST_APP_PKG + ".SimpleActivity";
        getDevice().executeShellCommand(command);
    }

    protected void setScreenCaptureDisabled(int userId, boolean disabled) throws Exception {
        String testMethodName = disabled
                ? "testSetScreenCaptureDisabled_true"
                : "testSetScreenCaptureDisabled_false";
        executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
        startSimpleActivityAsUser(userId);
        testMethodName = disabled
                ? "testScreenCaptureImpossible"
                : "testScreenCapturePossible";
        executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
    }

    protected void setScreenCaptureDisabled_assist(int userId, boolean disabled) throws Exception {
        // Set the policy.
        String testMethodName = disabled
                ? "testSetScreenCaptureDisabled_true"
                : "testSetScreenCaptureDisabled_false";
        executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
        // Make sure the foreground activity is from the target user.
        startSimpleActivityAsUser(userId);
        // Check whether the VoiceInteractionService can retrieve the screenshot.
        testMethodName = disabled
                ? "testScreenCaptureImpossible_assist"
                : "testScreenCapturePossible_assist";
        installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
        runDeviceTestsAsUser(
                DEVICE_ADMIN_PKG,
                ".AssistScreenCaptureDisabledTest",
                testMethodName,
                mPrimaryUserId);
    }

    /**
     * Allows packageName to manage notification policy configuration, which
     * includes toggling zen mode.
     */
    private void allowNotificationPolicyAccess(String packageName, int userId)
            throws DeviceNotAvailableException {
        List<String> enabledPackages = getEnabledNotificationPolicyPackages(userId);
        if (!enabledPackages.contains(packageName)) {
            enabledPackages.add(packageName);
            setEnabledNotificationPolicyPackages(enabledPackages, userId);
        }
    }

    /**
     * Disallows packageName to manage notification policy configuration, which
     * includes toggling zen mode.
     */
    private void disallowNotificationPolicyAccess(String packageName, int userId)
            throws DeviceNotAvailableException {
        List<String> enabledPackages = getEnabledNotificationPolicyPackages(userId);
        if (enabledPackages.contains(packageName)) {
            enabledPackages.remove(packageName);
            setEnabledNotificationPolicyPackages(enabledPackages, userId);
        }
    }

    private void setEnabledNotificationPolicyPackages(List<String> packages, int userId)
            throws DeviceNotAvailableException {
        getDevice().setSetting(userId, "secure", ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
                String.join(":", packages));
    }

    private List<String> getEnabledNotificationPolicyPackages(int userId)
            throws DeviceNotAvailableException {
        String settingValue = getDevice().getSetting(userId, "secure",
                ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
        if (settingValue == null) {
            return new ArrayList<String>();
        }
        return new ArrayList<String>(Arrays.asList(settingValue.split(":|\n")));
    }

    protected void setVoiceInteractionService(String componentName)
            throws DeviceNotAvailableException {
        getDevice().setSetting(
                mPrimaryUserId, "secure", "voice_interaction_service", componentName);
        getDevice().setSetting(mPrimaryUserId, "secure", "assist_structure_enabled", "1");
        getDevice().setSetting(mPrimaryUserId, "secure", "assist_screenshot_enabled", "1");
    }

    protected void clearVoiceInteractionService() throws DeviceNotAvailableException {
        getDevice().executeShellCommand("settings delete secure voice_interaction_service");
    }
}
