/*
 * 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 and
 * limitations under the License.
 */

package android.permission.cts;

import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.permissionToOp;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;

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

import android.app.AppOpsManager;
import android.app.UiAutomation;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PermissionInfo;
import android.os.Process;
import android.os.UserHandle;

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Common utils for permission tests
 */
public class PermissionUtils {
    private static final long TIMEOUT_MILLIS = 10000;

    private static final int TESTED_FLAGS = FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED
            | FLAG_PERMISSION_REVOKE_ON_UPGRADE | FLAG_PERMISSION_REVIEW_REQUIRED
            | FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;

    private static final Context sContext =
            InstrumentationRegistry.getInstrumentation().getTargetContext();
    private static final UiAutomation sUiAutomation =
            InstrumentationRegistry.getInstrumentation().getUiAutomation();

    private PermissionUtils() {
        // this class should never be instantiated
    }

    /**
     * Get the state of an app-op.
     *
     * @param packageName The package the app-op belongs to
     * @param permission The permission the app-op belongs to
     *
     * @return The mode the op is on
     */
    public static int getAppOp(@NonNull String packageName, @NonNull String permission)
            throws Exception {
        return callWithShellPermissionIdentity(
                () -> sContext.getSystemService(AppOpsManager.class).unsafeCheckOpRaw(
                        permissionToOp(permission),
                        sContext.getPackageManager().getPackageUid(packageName, 0), packageName));
    }

    /**
     * Install an APK.
     *
     * @param apkFile The apk to install
     */
    public static void install(@NonNull String apkFile) {
        runShellCommand("pm install -r --force-sdk " + apkFile);
    }

    /**
     * Uninstall a package.
     *
     * @param packageName Name of package to be uninstalled
     */
    public static void uninstallApp(@NonNull String packageName) {
        runShellCommand("pm uninstall " + packageName);
    }

    /**
     * Set a new state for an app-op (using the permission-name)
     *
     * @param packageName The package the app-op belongs to
     * @param permission The permission the app-op belongs to
     * @param mode The new mode
     */
    public static void setAppOp(@NonNull String packageName, @NonNull String permission, int mode) {
        setAppOpByName(packageName, permissionToOp(permission), mode);
    }

    /**
     * Set a new state for an app-op (using the app-op-name)
     *
     * @param packageName The package the app-op belongs to
     * @param op The name of the op
     * @param mode The new mode
     */
    public static void setAppOpByName(@NonNull String packageName, @NonNull String op, int mode) {
        runWithShellPermissionIdentity(
                () -> sContext.getSystemService(AppOpsManager.class).setUidMode(op,
                        sContext.getPackageManager().getPackageUid(packageName, 0), mode));
    }

    /**
     * Checks a permission. Does <u>not</u> check the appOp.
     *
     * <p>Users should use {@link #isGranted} instead.
     *
     * @param packageName The package that might have the permission granted
     * @param permission The permission that might be granted
     *
     * @return {@code true} iff the permission is granted
     */
    public static boolean isPermissionGranted(@NonNull String packageName,
            @NonNull String permission) throws Exception {
        return sContext.checkPermission(permission, Process.myPid(),
                sContext.getPackageManager().getPackageUid(packageName, 0))
                == PERMISSION_GRANTED;
    }

    /**
     * Checks if a permission is granted for a package.
     *
     * <p>This correctly handles pre-M apps by checking the app-ops instead.
     * <p>This also correctly handles the location background permission, but does not handle any
     * other background permission
     *
     * @param packageName The package that might have the permission granted
     * @param permission The permission that might be granted
     *
     * @return {@code true} iff the permission is granted
     */
    public static boolean isGranted(@NonNull String packageName, @NonNull String permission)
            throws Exception {
        if (!isPermissionGranted(packageName, permission)) {
            return false;
        }

        if (permission.equals(ACCESS_BACKGROUND_LOCATION)) {
            // The app-op for background location is encoded into the mode of the foreground
            // location
            return getAppOp(packageName, ACCESS_COARSE_LOCATION) == MODE_ALLOWED;
        } else {
            int mode = getAppOp(packageName, permission);
            return mode == MODE_ALLOWED || mode == MODE_FOREGROUND;
        }
    }

    /**
     * Grant a permission to an app.
     *
     * <p>This correctly handles pre-M apps by setting the app-ops.
     * <p>This also correctly handles the location background permission, but does not handle any
     * other background permission
     *
     * @param packageName The app that should have the permission granted
     * @param permission The permission to grant
     */
    public static void grantPermission(@NonNull String packageName, @NonNull String permission)
            throws Exception {
        sUiAutomation.grantRuntimePermission(packageName, permission);

        if (permission.equals(ACCESS_BACKGROUND_LOCATION)) {
            // The app-op for background location is encoded into the mode of the foreground
            // location
            if (isPermissionGranted(packageName, ACCESS_COARSE_LOCATION)) {
                setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_ALLOWED);
            } else {
                setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_FOREGROUND);
            }
        } else if (permission.equals(ACCESS_COARSE_LOCATION)) {
            // The app-op for location depends on the state of the bg location
            if (isPermissionGranted(packageName, ACCESS_BACKGROUND_LOCATION)) {
                setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_ALLOWED);
            } else {
                setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_FOREGROUND);
            }
        } else {
            setAppOp(packageName, permission, MODE_ALLOWED);
        }
    }

    /**
     * Revoke a permission from an app.
     *
     * <p>This correctly handles pre-M apps by setting the app-ops.
     * <p>This also correctly handles the location background permission, but does not handle any
     * other background permission
     *
     * @param packageName The app that should have the permission revoked
     * @param permission The permission to revoke
     */
    public static void revokePermission(@NonNull String packageName, @NonNull String permission)
            throws Exception {
        sUiAutomation.revokeRuntimePermission(packageName, permission);

        if (permission.equals(ACCESS_BACKGROUND_LOCATION)) {
            // The app-op for background location is encoded into the mode of the foreground
            // location
            if (isGranted(packageName, ACCESS_COARSE_LOCATION)) {
                setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_FOREGROUND);
            }
        } else {
            setAppOp(packageName, permission, MODE_IGNORED);
        }
    }

    /**
     * Clear permission state (not app-op state) of package.
     *
     * @param packageName Package to clear
     */
    public static void clearAppState(@NonNull String packageName) {
        runShellCommand("pm clear " + packageName);
    }

    /**
     * Get the flags of a permission.
     *
     * @param packageName Package the permission belongs to
     * @param permission Name of the permission
     *
     * @return Permission flags
     */
    public static int getPermissionFlags(@NonNull String packageName, @NonNull String permission) {
        try {
            return callWithShellPermissionIdentity(
                    () -> sContext.getPackageManager().getPermissionFlags(permission, packageName,
                            UserHandle.getUserHandleForUid(Process.myUid())) & TESTED_FLAGS);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Set the flags of a permission.
     *
     * @param packageName Package the permission belongs to
     * @param permission Name of the permission
     * @param mask Mask of permissions to set
     * @param flags Permissions to set
     */
    public static void setPermissionFlags(@NonNull String packageName, @NonNull String permission,
            int mask, int flags) {
        runWithShellPermissionIdentity(
                () -> sContext.getPackageManager().updatePermissionFlags(permission, packageName,
                        mask, flags, UserHandle.getUserHandleForUid(Process.myUid())));
    }

    /**
     * Get all permissions an app requests. This includes the split permissions.
     *
     * @param packageName The package that requests the permissions.
     *
     * @return The permissions requested by the app
     */
    public static @NonNull List<String> getPermissions(@NonNull String packageName)
            throws Exception {
        PackageInfo appInfo = sContext.getPackageManager().getPackageInfo(packageName,
                GET_PERMISSIONS);

        return Arrays.asList(appInfo.requestedPermissions);
    }

    /**
     * Get all runtime permissions that an app requests. This includes the split permissions.
     *
     * @param packageName The package that requests the permissions.
     *
     * @return The runtime permissions requested by the app
     */
    public static @NonNull List<String> getRuntimePermissions(@NonNull String packageName)
            throws Exception {
        ArrayList<String> runtimePermissions = new ArrayList<>();

        for (String perm : getPermissions(packageName)) {
            PermissionInfo info = sContext.getPackageManager().getPermissionInfo(perm, 0);
            if ((info.getProtection() & PROTECTION_DANGEROUS) != 0) {
                runtimePermissions.add(perm);
            }
        }

        return runtimePermissions;
    }

    public interface ThrowingRunnable extends Runnable {
        void runOrThrow() throws Exception;

        @Override
        default void run() {
            try {
                runOrThrow();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    /**
     * Make sure that a {@link Runnable} eventually finishes without throwing a {@link
     * Exception}.
     *
     * @param r The {@link Runnable} to run.
     */
    public static void eventually(@NonNull ThrowingRunnable r) {
        long start = System.currentTimeMillis();

        while (true) {
            try {
                r.run();
                return;
            } catch (Throwable e) {
                if (System.currentTimeMillis() - start < TIMEOUT_MILLIS) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ignored) {
                        throw new RuntimeException(e);
                    }
                } else {
                    throw e;
                }
            }
        }
    }
}
