/*
 * Copyright (C) 2019 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 andf
 * limitations under the License.
 */

package android.permission2.cts;

import static android.permission.cts.PermissionUtils.eventually;
import static android.permission.cts.PermissionUtils.isGranted;
import static android.permission.cts.PermissionUtils.isPermissionGranted;

import static com.android.compatibility.common.util.SystemUtil.runShellCommand;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.fail;

import android.Manifest;
import android.Manifest.permission;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.Session;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.permission.cts.PermissionUtils.ThrowingRunnable;
import android.platform.test.annotations.AppModeFull;
import android.util.ArraySet;

import androidx.annotation.NonNull;
import androidx.test.platform.app.InstrumentationRegistry;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nullable;

/**
 * Tests for restricted permission behaviors.
 */
public class RestrictedPermissionsTest {
    private static final String APK_USES_LOCATION_22 =
            "/data/local/tmp/cts/permissions2/CtsLocationPermissionsUserSdk22.apk";

    private static final String APK_USES_LOCATION_29 =
            "/data/local/tmp/cts/permissions2/CtsLocationPermissionsUserSdk29.apk";

    private static final String APK_USES_SMS_CALL_LOG_22 =
            "/data/local/tmp/cts/permissions2/CtsSMSCallLogPermissionsUserSdk22.apk";

    private static final String APK_NAME_USES_SMS_CALL_LOG_29 =
            "CtsSMSCallLogPermissionsUserSdk29.apk";

    private static final String APK_USES_SMS_CALL_LOG_29 =
            "/data/local/tmp/cts/permissions2/CtsSMSCallLogPermissionsUserSdk29.apk";

    private static final String APK_USES_STORAGE_DEFAULT_22 =
            "/data/local/tmp/cts/permissions2/CtsStoragePermissionsUserDefaultSdk22.apk";

    private static final String APK_USES_STORAGE_DEFAULT_28 =
            "/data/local/tmp/cts/permissions2/CtsStoragePermissionsUserDefaultSdk28.apk";

    private static final String APK_USES_STORAGE_DEFAULT_29 =
            "/data/local/tmp/cts/permissions2/CtsStoragePermissionsUserDefaultSdk29.apk";

    private static final String APK_USES_STORAGE_OPT_IN_22 =
            "/data/local/tmp/cts/permissions2/CtsStoragePermissionsUserOptInSdk22.apk";

    private static final String APK_USES_STORAGE_OPT_IN_28 =
            "/data/local/tmp/cts/permissions2/CtsStoragePermissionsUserOptInSdk28.apk";

    private static final String APK_USES_STORAGE_OPT_OUT_29 =
            "/data/local/tmp/cts/permissions2/CtsStoragePermissionsUserOptOutSdk29.apk";

    private static final String PKG = "android.permission2.cts.restrictedpermissionuser";

    private static final long UI_TIMEOUT = 5000L;

    private static @NonNull BroadcastReceiver sCommandReceiver;

    @BeforeClass
    public static void setUpOnce() {
        sCommandReceiver = new CommandBroadcastReceiver();
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("installRestrictedPermissionUserApp");
        intentFilter.addAction("uninstallApp");
        getContext().registerReceiver(sCommandReceiver, intentFilter);
    }

    @AfterClass
    public static void tearDownOnce() {
        getContext().unregisterReceiver(sCommandReceiver);
    }

    @Test
    @AppModeFull
    public void testDefaultAllRestrictedPermissionsWhitelistedAtInstall29() throws Exception {
        // Install with no changes to whitelisted permissions, not attempting to grant.
        installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
                Collections.EMPTY_SET /*grantedPermissions*/);

        // All restricted permission should be whitelisted.
        assertAllRestrictedPermissionWhitelisted();

        // No restricted permission should be granted.
        assertNoRestrictedPermissionGranted();
    }

    @Test
    @AppModeFull
    public void testSomeRestrictedPermissionsWhitelistedAtInstall29() throws Exception {
        // Whitelist only these permissions.
        final Set<String> whitelistedPermissions = new ArraySet<>(2);
        whitelistedPermissions.add(Manifest.permission.SEND_SMS);
        whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);

        // Install with some whitelisted permissions, not attempting to grant.
        installRestrictedPermissionUserApp(whitelistedPermissions,
                Collections.EMPTY_SET /*grantedPermissions*/);

        // Some restricted permission should be whitelisted.
        assertRestrictedPermissionWhitelisted(whitelistedPermissions);

        // No restricted permission should be granted.
        assertNoRestrictedPermissionGranted();
    }

    @Test
    @AppModeFull
    public void testNoneRestrictedPermissionWhitelistedAtInstall29() throws Exception {
        // Install with all whitelisted permissions, not attempting to grant.
        installRestrictedPermissionUserApp(Collections.emptySet(),
                Collections.EMPTY_SET /*grantedPermissions*/);

        // No restricted permission should be whitelisted.
        assertNoRestrictedPermissionWhitelisted();

        // No restricted permission should be granted.
        assertNoRestrictedPermissionGranted();
    }

    @Test
    @AppModeFull
    public void testDefaultAllRestrictedPermissionsWhitelistedAtInstall22() throws Exception {
        // Install with no changes to whitelisted permissions
        runShellCommand("pm install -g " + APK_USES_SMS_CALL_LOG_22);

        // All restricted permission should be whitelisted.
        assertAllRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void testSomeRestrictedPermissionsWhitelistedAtInstall22() throws Exception {
        // Whitelist only these permissions.
        final Set<String> whitelistedPermissions = new ArraySet<>(2);
        whitelistedPermissions.add(Manifest.permission.SEND_SMS);
        whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);

        // Install with some whitelisted permissions
        installApp(APK_USES_SMS_CALL_LOG_22, whitelistedPermissions, null /*grantedPermissions*/);

        // Some restricted permission should be whitelisted.
        assertRestrictedPermissionWhitelisted(whitelistedPermissions);
    }

    @Test
    @AppModeFull
    public void testNoneRestrictedPermissionWhitelistedAtInstall22() throws Exception {
        // Install with all whitelisted permissions
        installApp(APK_USES_SMS_CALL_LOG_22, Collections.emptySet(),
                null /*grantedPermissions*/);

        // No restricted permission should be whitelisted.
        assertNoRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void testLocationBackgroundPermissionWhitelistedAtInstall29() throws Exception {
        installApp(APK_USES_LOCATION_29, null, null);
        assertAllRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void testLocationBackgroundPermissionNotWhitelistedAtInstall29() throws Exception {
        installApp(APK_USES_LOCATION_29, Collections.EMPTY_SET, null);
        assertNoRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void testLocationBackgroundPermissionWhitelistedAtInstall22() throws Exception {
        installApp(APK_USES_LOCATION_22, null, null);
        assertAllRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void testLocationBackgroundPermissionNotWhitelistedAtInstall22() throws Exception {
        installApp(APK_USES_LOCATION_22, Collections.EMPTY_SET, null);
        assertNoRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void testSomeRestrictedPermissionsGrantedAtInstall() throws Exception {
        // Grant only these permissions.
        final Set<String> grantedPermissions = new ArraySet<>(1);
        grantedPermissions.add(Manifest.permission.SEND_SMS);
        grantedPermissions.add(Manifest.permission.READ_CALL_LOG);

        // Install with no whitelisted permissions attempting to grant.
        installRestrictedPermissionUserApp(null /*whitelistedPermissions*/, grantedPermissions);

        // All restricted permission should be whitelisted.
        assertAllRestrictedPermissionWhitelisted();

        // Some restricted permission should be granted.
        assertRestrictedPermissionGranted(grantedPermissions);
    }

    @Test
    @AppModeFull
    public void testCanGrantSoftRestrictedNotWhitelistedPermissions() throws Exception {
        try {
            final Set<String> grantedPermissions = new ArraySet<>();
            grantedPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
            grantedPermissions.add(permission.WRITE_EXTERNAL_STORAGE);

            installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet(), grantedPermissions);

            assertRestrictedPermissionGranted(grantedPermissions);
        } finally {
            uninstallApp();
        }
    }

    @Test
    @AppModeFull
    public void testAllRestrictedPermissionsGrantedAtInstall() throws Exception {
        // Install with whitelisted permissions attempting to grant.
        installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
                null);

        // All restricted permission should be whitelisted.
        assertAllRestrictedPermissionWhitelisted();

        // Some restricted permission should be granted.
        assertAllRestrictedPermissionGranted();
    }

    @Test
    @AppModeFull
    public void testWhitelistAccessControl() throws Exception {
        // Install with no whitelisted permissions not attempting to grant.
        installRestrictedPermissionUserApp(Collections.emptySet(), null);

        assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
                PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM);

        assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
                PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);

        assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
                PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk22DefaultWhitelistedHasFullAccess() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_22, null /*whitelistedPermissions*/);

        // Check expected storage mode
        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk22OptInWhitelistedHasIsolatedAccess() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_IN_22, null /*whitelistedPermissions*/);

        // Check expected storage mode
        assertHasIsolatedStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk28DefaultWhitelistedHasFullAccess() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);

        // Check expected storage mode
        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk28OptInWhitelistedHasIsolatedAccess() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);

        // Check expected storage mode
        assertHasIsolatedStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29DefaultWhitelistedHasIsolatedAccess() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet());

        // Check expected storage mode
        assertHasIsolatedStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29DefaultNotWhitelistedHasIsolatedAccess() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_29, null /*whitelistedPermissions*/);

        // Check expected storage mode
        assertHasIsolatedStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29OptOutWhitelistedHasFullAccess() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_OUT_29, null /*whitelistedPermissions*/);

        // Check expected storage mode
        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29OptOutNotWhitelistedHasIsolatedAccess() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_OUT_29, Collections.emptySet());

        // Check expected storage mode
        assertHasIsolatedStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29CanOptOutViaUpdate() throws Exception {
        installApp(APK_USES_STORAGE_DEFAULT_29, null);
        installApp(APK_USES_STORAGE_OPT_OUT_29, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29CanOptOutViaDowngradeTo28() throws Exception {
        installApp(APK_USES_STORAGE_DEFAULT_29, null);
        installApp(APK_USES_STORAGE_DEFAULT_28, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk28CanRemoveOptInViaUpdate() throws Exception {
        installApp(APK_USES_STORAGE_OPT_IN_28, null);
        installApp(APK_USES_STORAGE_DEFAULT_28, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk28CanRemoveOptInByOptingOut() throws Exception {
        installApp(APK_USES_STORAGE_OPT_IN_28, null);
        installApp(APK_USES_STORAGE_OPT_OUT_29, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk28DoesNotLooseAccessWhenOptingIn() throws Exception {
        installApp(APK_USES_STORAGE_DEFAULT_28, null);
        installApp(APK_USES_STORAGE_OPT_IN_28, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk28DoesNotLooseAccessViaUpdate() throws Exception {
        installApp(APK_USES_STORAGE_DEFAULT_28, null);
        installApp(APK_USES_STORAGE_DEFAULT_29, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29DoesNotLooseAccessViaUpdate() throws Exception {
        installApp(APK_USES_STORAGE_OPT_OUT_29, null);
        installApp(APK_USES_STORAGE_DEFAULT_29, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testStorageTargetingSdk29DoesNotLooseAccessWhenOptingIn() throws Exception {
        installApp(APK_USES_STORAGE_OPT_OUT_29, null);
        installApp(APK_USES_STORAGE_OPT_IN_28, null);

        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void testCannotControlStorageWhitelistPostInstall1() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);

        // Check expected state of restricted permissions.
        assertCannotUnWhitelistStorage();
    }

    @Test
    @AppModeFull
    public void testCannotControlStorageWhitelistPostInstall2() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());

        // Check expected state of restricted permissions.
        assertCannotWhitelistStorage();
    }

    @Test
    @AppModeFull
    public void cannotGrantStorageTargetingSdk22NotWhitelisted() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_22, Collections.emptySet(), null);

        eventually(() -> {
            // Could not grant permission+app-op as targetSDK<29 and not whitelisted
            assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse();

            // Permissions are always granted for pre-23 apps
            assertThat(
                    isPermissionGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue();
        });
    }

    @Test
    @AppModeFull
    public void cannotGrantStorageTargetingSdk22OptInNotWhitelisted() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_IN_22, Collections.emptySet(), null);

        eventually(() -> {
            // Could not grant permission as targetSDK<29 and not whitelisted
            assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse();

            // Permissions are always granted for pre-23 apps
            assertThat(
                    isPermissionGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue();
        });
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk22Whitelisted() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_22, null, null);

        // Could grant permission
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk22OptInWhitelisted() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_IN_22, null, null);

        // Could grant permission
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void cannotGrantStorageTargetingSdk28NotWhitelisted() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet(), null);

        // Could not grant permission as targetSDK<29 and not whitelisted
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse());
    }

    @Test
    @AppModeFull
    public void cannotGrantStorageTargetingSdk28OptInNotWhitelisted() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_IN_28, Collections.emptySet(), null);

        // Could not grant permission as targetSDK<29 and not whitelisted
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk28Whitelisted() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_28, null, null);

        // Could grant permission
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk28OptInWhitelisted() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_IN_28, null, null);

        // Could grant permission
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk29NotWhitelisted() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet(), null);

        // Could grant permission as targetSDK=29 apps can always grant
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk29OptOutNotWhitelisted() throws Exception {
        // Install with no whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_OUT_29, Collections.emptySet(), null);

        // Could grant permission as targetSDK=29 apps can always grant
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk29Whitelisted() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_DEFAULT_29, null, null);

        // Could grant permission as targetSDK=29 apps can always grant
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void canGrantStorageTargetingSdk29OptOutWhitelisted() throws Exception {
        // Install with whitelisted permissions.
        installApp(APK_USES_STORAGE_OPT_OUT_29, null, null);

        // Could grant permission as targetSDK=29 apps can always grant
        eventually(() -> assertThat(
                isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
    }

    @Test
    @AppModeFull
    public void restrictedWritePermDoesNotImplyIsolatedStorageAccess() throws Exception {
        // Install with whitelisted read permissions.
        installApp(APK_USES_STORAGE_OPT_OUT_29,
                Collections.singleton(Manifest.permission.READ_EXTERNAL_STORAGE), null);

        // It does not matter that write is restricted as the storage access level is only
        // controlled by the read perm
        assertHasFullStorageAccess();
    }

    @Test
    @AppModeFull
    public void whitelistedWritePermDoesNotImplyFullStorageAccess() throws Exception {
        // Install with whitelisted read permissions.
        installApp(APK_USES_STORAGE_OPT_OUT_29,
                Collections.singleton(Manifest.permission.WRITE_EXTERNAL_STORAGE), null);

        // It does not matter that write is white listed as the storage access level is only
        // controlled by the read perm
        assertHasIsolatedStorageAccess();
    }

    @Test
    @AppModeFull
    public void onSideLoadRestrictedPermissionsWhitelistingDefault() throws Exception {
        installRestrictedPermissionUserApp(new SessionParams(SessionParams.MODE_FULL_INSTALL));

        // All restricted permissions whitelisted on side-load by default
        assertAllRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void onSideLoadAllRestrictedPermissionsWhitelisted() throws Exception {
        SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
        params.setWhitelistedRestrictedPermissions(SessionParams.RESTRICTED_PERMISSIONS_ALL);

        installRestrictedPermissionUserApp(params);

        assertAllRestrictedPermissionWhitelisted();
    }

    @Test
    @AppModeFull
    public void onSideLoadWhitelistSomePermissions() throws Exception {
        Set<String> whitelistedPermissions = new ArraySet<>();
        whitelistedPermissions.add(Manifest.permission.SEND_SMS);
        whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);

        SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
        params.setWhitelistedRestrictedPermissions(whitelistedPermissions);

        installRestrictedPermissionUserApp(params);

        assertRestrictedPermissionWhitelisted(whitelistedPermissions);
    }

    @Test
    @AppModeFull
    public void onSideLoadWhitelistNoPermissions() throws Exception {
        SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
        params.setWhitelistedRestrictedPermissions(Collections.emptySet());

        installRestrictedPermissionUserApp(params);

        assertNoRestrictedPermissionWhitelisted();
    }

    private static void installRestrictedPermissionUserApp(@NonNull SessionParams params)
            throws Exception {
        final CountDownLatch installLatch = new CountDownLatch(1);

        // Create an install result receiver.
        final BroadcastReceiver installReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                if (intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
                        PackageInstaller.STATUS_FAILURE_INVALID)
                            == PackageInstaller.STATUS_SUCCESS) {
                    installLatch.countDown();
                }
            }
        };

        // Register the result receiver.
        final String action = "android.permission2.cts.ACTION_INSTALL_COMMIT";
        final IntentFilter intentFilter = new IntentFilter(action);
        getContext().registerReceiver(installReceiver, intentFilter);

        try {
            // Create a session.
            final PackageInstaller packageInstaller = getContext()
                    .getPackageManager().getPackageInstaller();
            final int sessionId = packageInstaller.createSession(params);
            final Session session = packageInstaller.openSession(sessionId);

            // Write the apk.
            try (
                    InputStream in = new BufferedInputStream(new FileInputStream(
                        new File(APK_USES_SMS_CALL_LOG_29)));
                    OutputStream out = session.openWrite(
                            APK_NAME_USES_SMS_CALL_LOG_29, 0, -1);
            ) {
                final byte[] buf = new byte[8192];
                int size;
                while ((size = in.read(buf)) != -1) {
                    out.write(buf, 0, size);
                }
            }

            final Intent intent = new Intent(action);
            final IntentSender intentSender = PendingIntent.getBroadcast(getContext(),
                    1, intent, PendingIntent.FLAG_ONE_SHOT).getIntentSender();

            // Commit as shell to avoid confirm UI
            runWithShellPermissionIdentity(() ->
                session.commit(intentSender)
            );

            installLatch.await(UI_TIMEOUT, TimeUnit.MILLISECONDS);
        } finally {
            getContext().unregisterReceiver(installReceiver);
        }
    }

    private void assertHasFullStorageAccess() throws Exception {
        runWithShellPermissionIdentity(() -> {
            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
            final int uid = getContext().getPackageManager().getPackageUid(PKG, 0);
            eventually(() -> assertThat(appOpsManager.unsafeCheckOpRawNoThrow(
                    AppOpsManager.OPSTR_LEGACY_STORAGE,
                    uid, PKG)).isEqualTo(AppOpsManager.MODE_ALLOWED));
        });
    }

    private void assertHasIsolatedStorageAccess() throws Exception {
        runWithShellPermissionIdentity(() -> {
            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
            final int uid = getContext().getPackageManager().getPackageUid(PKG, 0);
            eventually(() -> assertThat(appOpsManager.unsafeCheckOpRawNoThrow(
                    AppOpsManager.OPSTR_LEGACY_STORAGE,
                    uid, PKG)).isNotEqualTo(AppOpsManager.MODE_ALLOWED));
        });
    }

    private void assertWeCannotReadOrWriteWhileShellCanReadAndWrite(int whitelist)
            throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();
        try {
            packageManager.getWhitelistedRestrictedPermissions(PKG, whitelist);
            fail();
        } catch (SecurityException expected) {
            /*ignore*/
        }
        try {
            packageManager.addWhitelistedRestrictedPermission(PKG,
                    permission.SEND_SMS, whitelist);
            fail();
        } catch (SecurityException expected) {
            /*ignore*/
        }
        runWithShellPermissionIdentity(() -> {
            packageManager.addWhitelistedRestrictedPermission(PKG,
                    permission.SEND_SMS, whitelist);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    whitelist)).contains(permission.SEND_SMS);
            packageManager.removeWhitelistedRestrictedPermission(PKG,
                    permission.SEND_SMS, whitelist);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    whitelist)).doesNotContain(permission.SEND_SMS);
        });
    }

    private void assertCannotWhitelistStorage()
            throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();

        runWithShellPermissionIdentity(() -> {
            // Assert added only to none whitelist.
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
                            | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .doesNotContain(permission.READ_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
                            | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
        });

        // Assert we cannot add.
        try {
            packageManager.addWhitelistedRestrictedPermission(PKG,
                    permission.READ_EXTERNAL_STORAGE,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
            fail();
        } catch (SecurityException expected) {}
        try {
            packageManager.addWhitelistedRestrictedPermission(PKG,
                    permission.WRITE_EXTERNAL_STORAGE,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
            fail();
        } catch (SecurityException expected) {}

        runWithShellPermissionIdentity(() -> {
            // Assert added only to none whitelist.
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
                            | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .doesNotContain(permission.READ_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
                            | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
        });
    }

    private void assertCannotUnWhitelistStorage()
            throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();

        runWithShellPermissionIdentity(() -> {
            // Assert added only to install whitelist.
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .contains(permission.READ_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .contains(permission.WRITE_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
                    .doesNotContain(permission.READ_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
                    .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
        });

        try {
            // Assert we cannot remove.
            packageManager.removeWhitelistedRestrictedPermission(PKG,
                    permission.READ_EXTERNAL_STORAGE,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
            fail();
        } catch (SecurityException expected) {}
        try {
            packageManager.removeWhitelistedRestrictedPermission(PKG,
                    permission.WRITE_EXTERNAL_STORAGE,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
            fail();
        } catch (SecurityException expected) {}

        runWithShellPermissionIdentity(() -> {
            // Assert added only to install whitelist.
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .contains(permission.READ_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
                    .contains(permission.WRITE_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
                    .doesNotContain(permission.READ_EXTERNAL_STORAGE);
            assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
                    PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
                            | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
                    .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
        });
    }

    private @NonNull Set<String> getPermissionsOfAppWithAnyOfFlags(int flags) throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();

        final PackageInfo packageInfo = packageManager.getPackageInfo(PKG,
                PackageManager.GET_PERMISSIONS);

        final Set<String> hardRestrictedPermissions = new ArraySet<>();
        for (String permission : packageInfo.requestedPermissions) {
            PermissionInfo permInfo = packageManager.getPermissionInfo(permission, 0);

            if ((permInfo.flags & flags) != 0) {
                hardRestrictedPermissions.add(permission);
            }
        }

        return hardRestrictedPermissions;
    }

    private @NonNull Set<String> getRestrictedPermissionsOfApp() throws Exception {
        return getPermissionsOfAppWithAnyOfFlags(
                PermissionInfo.FLAG_HARD_RESTRICTED | PermissionInfo.FLAG_SOFT_RESTRICTED);
    }

    private void assertAllRestrictedPermissionWhitelisted() throws Exception {
        assertRestrictedPermissionWhitelisted(getRestrictedPermissionsOfApp());
    }

    private void assertNoRestrictedPermissionWhitelisted() throws Exception {
        assertRestrictedPermissionWhitelisted(
                Collections.EMPTY_SET /*expectedWhitelistedPermissions*/);
    }

    /**
     * Assert that the passed in restrictions are whitelisted and that their app-op is set
     * correctly.
     *
     * @param expectedWhitelistedPermissions The expected white listed permissions
     */
    private void assertRestrictedPermissionWhitelisted(
            @NonNull Set<String> expectedWhitelistedPermissions) throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();
    eventually(() -> runWithShellPermissionIdentity(() -> {
            final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
            final PackageInfo packageInfo = packageManager.getPackageInfo(PKG,
                    PackageManager.GET_PERMISSIONS);

            final Set<String> whitelistedPermissions = packageManager
                .getWhitelistedRestrictedPermissions(PKG,
                        PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
                        | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);

            assertThat(whitelistedPermissions).isNotNull();
            assertThat(whitelistedPermissions).named("Whitelisted permissions")
                    .containsExactlyElementsIn(expectedWhitelistedPermissions);

            // Also assert that apps ops are properly set
            for (String permission : getRestrictedPermissionsOfApp()) {
                String op = AppOpsManager.permissionToOp(permission);
                ArraySet<Integer> possibleModes = new ArraySet<>();

                if (permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
                    op = AppOpsManager.OPSTR_FINE_LOCATION;

                    // If permission is denied app-op might be allowed/fg or ignored. It does
                    // not matter. If permission is granted, it has to be allowed/fg.
                    if (isPermissionGranted(PKG, Manifest.permission.ACCESS_FINE_LOCATION)) {
                        if (expectedWhitelistedPermissions.contains(permission)
                                && isPermissionGranted(PKG, permission)) {
                            possibleModes.add(AppOpsManager.MODE_ALLOWED);
                        } else {
                            possibleModes.add(AppOpsManager.MODE_FOREGROUND);
                        }
                    } else {
                        possibleModes.add(AppOpsManager.MODE_IGNORED);
                        possibleModes.add(AppOpsManager.MODE_ALLOWED);
                        possibleModes.add(AppOpsManager.MODE_FOREGROUND);
                    }
                } else {
                    if (expectedWhitelistedPermissions.contains(permission)) {
                        // If permission is denied app-op might be allowed or ignored. It does not
                        // matter. If permission is granted, it has to be allowed.
                        possibleModes.add(AppOpsManager.MODE_ALLOWED);
                        if (!isPermissionGranted(PKG, permission)) {
                            possibleModes.add(AppOpsManager.MODE_IGNORED);
                        }
                    } else {
                        possibleModes.add(AppOpsManager.MODE_DEFAULT);
                    }
                }

                assertThat(appOpsManager.unsafeCheckOpRawNoThrow(op,
                        packageInfo.applicationInfo.uid, PKG)).named(op).isIn(possibleModes);
            }
        }));
    }

    private void assertAllRestrictedPermissionGranted() throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();
        final PackageInfo packageInfo = packageManager.getPackageInfo(
                PKG, PackageManager.GET_PERMISSIONS);
        if (packageInfo.requestedPermissions != null) {
            final int permissionCount = packageInfo.requestedPermissions.length;
            for (int i = 0; i < permissionCount; i++) {
                final String permission = packageInfo.requestedPermissions[i];
                final PermissionInfo permissionInfo = packageManager.getPermissionInfo(
                        permission, 0);
                if ((permissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0) {
                    assertThat((packageInfo.requestedPermissionsFlags[i]
                            & PackageInfo.REQUESTED_PERMISSION_GRANTED)).isNotEqualTo(0);
                }
            }
        }
    }

    private void assertNoRestrictedPermissionGranted() throws Exception {
        assertRestrictedPermissionGranted(Collections.EMPTY_SET);
    }

    private void assertRestrictedPermissionGranted(@NonNull Set<String> expectedGrantedPermissions)
            throws Exception {
        final PackageManager packageManager = getContext().getPackageManager();
        final PackageInfo packageInfo = packageManager.getPackageInfo(
                PKG, PackageManager.GET_PERMISSIONS);
        if (packageInfo.requestedPermissions != null) {
            final int permissionCount = packageInfo.requestedPermissions.length;
            for (int i = 0; i < permissionCount; i++) {
                final String permission = packageInfo.requestedPermissions[i];
                final PermissionInfo permissionInfo = packageManager.getPermissionInfo(
                        permission, 0);
                if ((permissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0
                        || (permissionInfo.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) {
                    if (expectedGrantedPermissions.contains(permission)) {
                        assertThat((packageInfo.requestedPermissionsFlags[i]
                                & PackageInfo.REQUESTED_PERMISSION_GRANTED)).isNotEqualTo(0);
                    } else {
                        assertThat((packageInfo.requestedPermissionsFlags[i]
                                & PackageInfo.REQUESTED_PERMISSION_GRANTED)).isEqualTo(0);
                    }
                }
            }
        }
    }

    /**
     * Install {@link #APK_USES_SMS_CALL_LOG_29}.
     *
     * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
     * @param grantedPermissions The permission to be granted. {@code null} == all
     */
    private void installRestrictedPermissionUserApp(@Nullable Set<String> whitelistedPermissions,
            @Nullable Set<String> grantedPermissions) throws Exception {
        installApp(APK_USES_SMS_CALL_LOG_29, whitelistedPermissions, grantedPermissions);
    }

    /**
     * Install app and grant all permission.
     *
     * @param app The app to be installed
     * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
     */
    private void installApp(@NonNull String app, @Nullable Set<String> whitelistedPermissions)
            throws Exception {
        installApp(app, whitelistedPermissions, null /*grantedPermissions*/);
    }

    /**
     * Install an app.
     *
     * @param app The app to be installed
     * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
     * @param grantedPermissions The permission to be granted. {@code null} == all
     */
    private void installApp(@NonNull String app, @Nullable Set<String> whitelistedPermissions,
            @Nullable Set<String> grantedPermissions) throws Exception {
        // Install the app and whitelist/grant all permission if requested.
        String installResult = runShellCommand("pm install -r --restrict-permissions " + app);
        assertThat(installResult.trim()).isEqualTo("Success");

        final Set<String> adjustedWhitelistedPermissions;
        if (whitelistedPermissions == null) {
            adjustedWhitelistedPermissions = getRestrictedPermissionsOfApp();
        } else {
            adjustedWhitelistedPermissions = whitelistedPermissions;
        }

        final Set<String> adjustedGrantedPermissions;
        if (grantedPermissions == null) {
            adjustedGrantedPermissions = getRestrictedPermissionsOfApp();
        } else {
            adjustedGrantedPermissions = grantedPermissions;
        }

        // Whitelist subset of permissions if requested
        runWithShellPermissionIdentity(() -> {
            final PackageManager packageManager = getContext().getPackageManager();
            for (String permission : adjustedWhitelistedPermissions) {
                packageManager.addWhitelistedRestrictedPermission(PKG, permission,
                        PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
            }
        });

        // Grant subset of permissions if requested
        runWithShellPermissionIdentity(() -> {
            final PackageManager packageManager = getContext().getPackageManager();
            for (String permission : adjustedGrantedPermissions) {
                packageManager.grantRuntimePermission(PKG, permission,
                        getContext().getUser());
            }
        });

        // Mark all permissions as reviewed as for pre-22 apps the restriction state might not be
        // applied until reviewed
        runWithShellPermissionIdentity(() -> {
            final PackageManager packageManager = getContext().getPackageManager();
            for (String permission : getRestrictedPermissionsOfApp()) {
                packageManager.updatePermissionFlags(permission, PKG,
                        PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0,
                        getContext().getUser());
            }
        });
    }

    @After
    public void uninstallApp() {
        runShellCommand("pm uninstall " + PKG);
    }

    private static @NonNull Context getContext() {
        return InstrumentationRegistry.getInstrumentation().getContext();
    }

    private static void runWithShellPermissionIdentity(@NonNull ThrowingRunnable command)
            throws Exception {
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity();
        try {
            command.runOrThrow();
        } finally {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .dropShellPermissionIdentity();
        }
    }
}
