/*
 * 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.deviceandprofileowner;

import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiWatcher;
import android.support.test.uiautomator.Until;
import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * Test Runtime Permissions APIs in DevicePolicyManager.
 */
public class PermissionsTest extends BaseDeviceAdminTest {
    private static final String TAG = "PermissionsTest";

    private static final String PERMISSION_APP_PACKAGE_NAME
            = "com.android.cts.permissionapp";
    private static final String SIMPLE_PRE_M_APP_PACKAGE_NAME =
            "com.android.cts.launcherapps.simplepremapp";
    private static final String PERMISSION_NAME = "android.permission.READ_CONTACTS";
    private static final String CUSTOM_PERM_A_NAME = "com.android.cts.permissionapp.permA";
    private static final String CUSTOM_PERM_B_NAME = "com.android.cts.permissionapp.permB";
    private static final String DEVELOPMENT_PERMISSION = "android.permission.INTERACT_ACROSS_USERS";

    private static final String PERMISSIONS_ACTIVITY_NAME
            = PERMISSION_APP_PACKAGE_NAME + ".PermissionActivity";
    private static final String ACTION_CHECK_HAS_PERMISSION
            = "com.android.cts.permission.action.CHECK_HAS_PERMISSION";
    private static final String ACTION_REQUEST_PERMISSION
            = "com.android.cts.permission.action.REQUEST_PERMISSION";
    private static final String ACTION_PERMISSION_RESULT
            = "com.android.cts.permission.action.PERMISSION_RESULT";
    private static final String EXTRA_PERMISSION
            = "com.android.cts.permission.extra.PERMISSION";
    private static final String EXTRA_GRANT_STATE
            = "com.android.cts.permission.extra.GRANT_STATE";
    private static final int PERMISSION_ERROR = -2;
    private static final BySelector CRASH_POPUP_BUTTON_SELECTOR = By
            .clazz(android.widget.Button.class.getName())
            .text("OK")
            .pkg("android");
    private static final BySelector CRASH_POPUP_TEXT_SELECTOR = By
            .clazz(android.widget.TextView.class.getName())
            .pkg("android");
    private static final String CRASH_WATCHER_ID = "CRASH";

    private PermissionBroadcastReceiver mReceiver;
    private PackageManager mPackageManager;
    private UiDevice mDevice;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mReceiver = new PermissionBroadcastReceiver();
        mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PERMISSION_RESULT));
        mPackageManager = mContext.getPackageManager();
        mDevice = UiDevice.getInstance(getInstrumentation());
    }

    @Override
    protected void tearDown() throws Exception {
        mContext.unregisterReceiver(mReceiver);
        mDevice.removeWatcher(CRASH_WATCHER_ID);
        super.tearDown();
    }

    public void testPermissionGrantState() throws Exception {
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        assertPermissionGrantState(PackageManager.PERMISSION_DENIED);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);

        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        // Should stay denied
        assertPermissionGrantState(PackageManager.PERMISSION_DENIED);

        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
        assertPermissionGrantState(PackageManager.PERMISSION_GRANTED);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);

        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        // Should stay granted
        assertPermissionGrantState(PackageManager.PERMISSION_GRANTED);
    }

    public void testPermissionPolicy() throws Exception {
        // reset permission to denied and unlocked
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);
        // permission should be locked, so changing the policy should not change the grant state
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);

        // reset permission to denied and unlocked
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
        // permission should be locked, so changing the policy should not change the grant state
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
    }

    public void testPermissionMixedPolicies() throws Exception {
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);

        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
    }

    public void testPermissionGrantOfDisallowedPermissionWhileOtherPermIsGranted() throws Exception {
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
                CUSTOM_PERM_A_NAME);
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED,
                CUSTOM_PERM_B_NAME);

        /*
         * CUSTOM_PERM_A_NAME and CUSTOM_PERM_B_NAME are in the same permission group and one is
         * granted the other one is not.
         *
         * It should not be possible to get the permission that was denied via policy granted by
         * requesting it.
         */
        assertPermissionRequest(PackageManager.PERMISSION_DENIED, null, CUSTOM_PERM_B_NAME);
    }

    @Suppress // Flakey.
    public void testPermissionPrompts() throws Exception {
        // register a crash watcher
        mDevice.registerWatcher(CRASH_WATCHER_ID, new UiWatcher() {
            @Override
            public boolean checkForCondition() {
                UiObject2 button = mDevice.findObject(CRASH_POPUP_BUTTON_SELECTOR);
                if (button != null) {
                    UiObject2 text = mDevice.findObject(CRASH_POPUP_TEXT_SELECTOR);
                    Log.d(TAG, "Removing an error dialog: " + text != null ? text.getText() : null);
                    button.click();
                    return true;
                }
                return false;
            }
        });
        mDevice.runWatchers();

        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED, "permission_deny_button");
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED, "permission_allow_button");
    }

    public void testPermissionUpdate_setDeniedState() throws Exception {
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
    }

    public void testPermissionUpdate_setAutoDeniedPolicy() throws Exception {
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);
    }

    public void testPermissionUpdate_checkDenied() throws Exception {
        assertPermissionRequest(PackageManager.PERMISSION_DENIED);
        assertPermissionGrantState(PackageManager.PERMISSION_DENIED);
    }

    public void testPermissionUpdate_setGrantedState() throws Exception {
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
    }

    public void testPermissionUpdate_setAutoGrantedPolicy() throws Exception {
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
    }

    public void testPermissionUpdate_checkGranted() throws Exception {
        assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
        assertPermissionGrantState(PackageManager.PERMISSION_GRANTED);
    }

    public void testPermissionGrantStateAppPreMDeviceAdminPreQ() throws Exception {
        // These tests are to make sure that pre-M apps are not granted/denied runtime permissions
        // by a profile owner that targets pre-Q
        assertCannotSetPermissionGrantStateAppPreM(
                DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        assertCannotSetPermissionGrantStateAppPreM(
                DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
    }

    public void testPermissionGrantStatePreMApp() throws Exception {
        // These tests are to make sure that pre-M apps can be granted/denied runtime permissions
        // by a profile owner targets Q or later
        assertCanSetPermissionGrantStateAppPreM(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        assertCanSetPermissionGrantStateAppPreM(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
    }

    public void testPermissionGrantState_developmentPermission() throws Exception {
        assertFailedToSetDevelopmentPermissionGrantState(
                DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
        assertFailedToSetDevelopmentPermissionGrantState(
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        assertFailedToSetDevelopmentPermissionGrantState(
                DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
    }

    private void assertPermissionRequest(int expected) throws Exception {
        assertPermissionRequest(expected, null);
    }

    private void assertPermissionRequest(int expected, String buttonResource) throws Exception {
        assertPermissionRequest(expected, buttonResource, PERMISSION_NAME);
    }

    private void assertPermissionRequest(int expected, String buttonResource, String permission)
            throws Exception {
        Intent launchIntent = new Intent();
        launchIntent.setComponent(new ComponentName(PERMISSION_APP_PACKAGE_NAME,
                PERMISSIONS_ACTIVITY_NAME));
        launchIntent.putExtra(EXTRA_PERMISSION, permission);
        launchIntent.setAction(ACTION_REQUEST_PERMISSION);
        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        mContext.startActivity(launchIntent);
        pressPermissionPromptButton(buttonResource);
        assertEquals(expected, mReceiver.waitForBroadcast());
        assertEquals(expected, mPackageManager.checkPermission(permission,
                PERMISSION_APP_PACKAGE_NAME));
    }

    private void assertPermissionGrantState(int expected) throws Exception {
        assertEquals(expected, mPackageManager.checkPermission(PERMISSION_NAME,
                PERMISSION_APP_PACKAGE_NAME));
        Intent launchIntent = new Intent();
        launchIntent.setComponent(new ComponentName(PERMISSION_APP_PACKAGE_NAME,
                PERMISSIONS_ACTIVITY_NAME));
        launchIntent.putExtra(EXTRA_PERMISSION, PERMISSION_NAME);
        launchIntent.setAction(ACTION_CHECK_HAS_PERMISSION);
        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        mContext.startActivity(launchIntent);
        assertEquals(expected, mReceiver.waitForBroadcast());
    }

    private void assertSetPermissionPolicy(int value) throws Exception {
        mDevicePolicyManager.setPermissionPolicy(ADMIN_RECEIVER_COMPONENT,
                value);
        assertEquals(mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT),
                value);
    }

    private void assertSetPermissionGrantState(int value) throws Exception {
        assertSetPermissionGrantState(value, PERMISSION_NAME);
    }
    private void assertSetPermissionGrantState(int value, String permission) throws Exception {
        mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, permission,
                value);
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, permission),
                value);
    }

    private void assertFailedToSetDevelopmentPermissionGrantState(int value) throws Exception {
        assertFalse(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, DEVELOPMENT_PERMISSION, value));
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                PERMISSION_APP_PACKAGE_NAME, DEVELOPMENT_PERMISSION),
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
        assertEquals(mPackageManager.checkPermission(DEVELOPMENT_PERMISSION,
                PERMISSION_APP_PACKAGE_NAME),
                PackageManager.PERMISSION_DENIED);
    }

    private void assertCannotSetPermissionGrantStateAppPreM(int value) throws Exception {
        assertFalse(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME,
                value));
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME),
                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);

        // Install time permissions should always be granted
        PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
                SIMPLE_PRE_M_APP_PACKAGE_NAME, 0);
        assertEquals(PackageManager.PERMISSION_GRANTED,
                PermissionChecker.checkPermission(mContext, PERMISSION_NAME, -1,
                        packageInfo.applicationInfo.uid, SIMPLE_PRE_M_APP_PACKAGE_NAME));
    }

    private void assertCanSetPermissionGrantStateAppPreM(int value) throws Exception {
        assertTrue(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME,
                value));
        assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
                SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME),
                value);

        // Install time permissions should always be granted
        assertEquals(mPackageManager.checkPermission(PERMISSION_NAME,
                SIMPLE_PRE_M_APP_PACKAGE_NAME),
                PackageManager.PERMISSION_GRANTED);

        PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
                SIMPLE_PRE_M_APP_PACKAGE_NAME, 0);

        // For pre-M apps the access to the data might be prevented via app-ops. Hence check that
        // they are correctly set
        boolean isGranted = (PermissionChecker.checkPermission(mContext, PERMISSION_NAME, -1,
                packageInfo.applicationInfo.uid, SIMPLE_PRE_M_APP_PACKAGE_NAME)
                == PackageManager.PERMISSION_GRANTED);
        switch (value) {
            case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED:
                assertTrue(isGranted);
                break;
            case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED:
                assertFalse(isGranted);
                break;
            default:
                fail("unsupported policy value");
        }
    }

    private void pressPermissionPromptButton(String resName) throws Exception {
        if (resName == null) {
            return;
        }

        BySelector selector = By
                .clazz(android.widget.Button.class.getName())
                .res("com.android.packageinstaller", resName);
        mDevice.wait(Until.hasObject(selector), 5000);
        UiObject2 button = mDevice.findObject(selector);
        assertNotNull("Couldn't find button with resource id: " + resName, button);
        button.click();
    }

    private class PermissionBroadcastReceiver extends BroadcastReceiver {
        private BlockingQueue<Integer> mQueue = new ArrayBlockingQueue<Integer> (1);

        @Override
        public void onReceive(Context context, Intent intent) {
            Integer result = new Integer(intent.getIntExtra(EXTRA_GRANT_STATE, PERMISSION_ERROR));
            Log.d(TAG, "Grant state received " + result);
            assertTrue(mQueue.add(result));
        }

        public int waitForBroadcast() throws Exception {
            Integer result = mQueue.poll(30, TimeUnit.SECONDS);
            mQueue.clear();
            assertNotNull(result);
            Log.d(TAG, "Grant state retrieved " + result.intValue());
            return result.intValue();
        }
    }
}
