/*
 * 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 com.android.server.policy;

import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_NONE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.permission.PermissionControllerManager;
import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

/**
 * This is a permission policy that governs over all permission mechanism
 * such as permissions, app ops, etc. For example, the policy ensures that
 * permission state and app ops is synchronized for cases where there is a
 * dependency between permission state (permissions or permission flags)
 * and app ops - and vise versa.
 */
public final class PermissionPolicyService extends SystemService {
    private static final String LOG_TAG = PermissionPolicyService.class.getSimpleName();
    private static final boolean DEBUG = false;

    private final Object mLock = new Object();

    /** Whether the user is started but not yet stopped */
    @GuardedBy("mLock")
    private final SparseBooleanArray mIsStarted = new SparseBooleanArray();

    /**
     * Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
     * scheduled for a package/user.
     */
    @GuardedBy("mLock")
    private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();

    public PermissionPolicyService(@NonNull Context context) {
        super(context);

        LocalServices.addService(PermissionPolicyInternal.class, new Internal());
    }

    @Override
    public void onStart() {
        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        final PermissionManagerServiceInternal permManagerInternal = LocalServices.getService(
                PermissionManagerServiceInternal.class);
        final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
                ServiceManager.getService(Context.APP_OPS_SERVICE));

        packageManagerInternal.getPackageList(new PackageListObserver() {
            @Override
            public void onPackageAdded(String packageName, int uid) {
                onPackageChanged(packageName, uid);
            }

            @Override
            public void onPackageChanged(String packageName, int uid) {
                final int userId = UserHandle.getUserId(uid);

                if (isStarted(userId)) {
                    synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
                }
            }

            @Override
            public void onPackageRemoved(String packageName, int uid) {
                /* do nothing */
            }
        });

        permManagerInternal.addOnRuntimePermissionStateChangedListener(
                this::synchronizePackagePermissionsAndAppOpsAsyncForUser);

        IAppOpsCallback appOpsListener = new IAppOpsCallback.Stub() {
            public void opChanged(int op, int uid, String packageName) {
                synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
                        UserHandle.getUserId(uid));
            }
        };

        final ArrayList<PermissionInfo> dangerousPerms =
                permManagerInternal.getAllPermissionWithProtectionLevel(
                        PermissionInfo.PROTECTION_DANGEROUS);

        try {
            int numDangerousPerms = dangerousPerms.size();
            for (int i = 0; i < numDangerousPerms; i++) {
                PermissionInfo perm = dangerousPerms.get(i);

                if (perm.isHardRestricted() || perm.backgroundPermission != null) {
                    appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
                            null, appOpsListener);
                } else if (perm.isSoftRestricted()) {
                    appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
                            null, appOpsListener);

                    SoftRestrictedPermissionPolicy policy =
                            SoftRestrictedPermissionPolicy.forPermission(null, null, null,
                                    perm.name);
                    if (policy.resolveAppOp() != OP_NONE) {
                        appOpsService.startWatchingMode(policy.resolveAppOp(), null,
                                appOpsListener);
                    }
                }
            }
        } catch (RemoteException doesNotHappen) {
            Slog.wtf(LOG_TAG, "Cannot set up app-ops listener");
        }
    }

    private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
            @UserIdInt int changedUserId) {
        if (isStarted(changedUserId)) {
            synchronized (mLock) {
                if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
                    FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
                            PermissionPolicyService
                                    ::synchronizePackagePermissionsAndAppOpsForUser,
                            this, packageName, changedUserId));
                } else {
                    if (DEBUG) {
                        Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
                                + " already scheduled");
                    }
                }
            }
        }
    }

    @Override
    public void onBootPhase(int phase) {
        if (DEBUG) Slog.i(LOG_TAG, "onBootPhase(" + phase + ")");

        if (phase == PHASE_ACTIVITY_MANAGER_READY) {
            final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);

            // For some users we might not receive a onStartUser, hence force one here
            for (int userId : um.getUserIds()) {
                if (um.isUserRunning(userId)) {
                    onStartUser(userId);
                }
            }
        }
    }

    /**
     * @return Whether the user is started but not yet stopped
     */
    private boolean isStarted(@UserIdInt int userId) {
        synchronized (mLock) {
            return mIsStarted.get(userId);
        }
    }

    @Override
    public void onStartUser(@UserIdInt int userId) {
        if (DEBUG) Slog.i(LOG_TAG, "onStartUser(" + userId + ")");

        if (isStarted(userId)) {
            return;
        }

        grantOrUpgradeDefaultRuntimePermissionsIfNeeded(userId);

        synchronized (mLock) {
            mIsStarted.put(userId, true);
        }

        // Force synchronization as permissions might have changed
        synchronizePermissionsAndAppOpsForUser(userId);
    }

    @Override
    public void onStopUser(@UserIdInt int userId) {
        if (DEBUG) Slog.i(LOG_TAG, "onStopUser(" + userId + ")");

        synchronized (mLock) {
            mIsStarted.delete(userId);
        }
    }

    private void grantOrUpgradeDefaultRuntimePermissionsIfNeeded(@UserIdInt int userId) {
        if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPermsIfNeeded(" + userId + ")");

        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        if (packageManagerInternal.wereDefaultPermissionsGrantedSinceBoot(userId)) {
            if (DEBUG) Slog.i(LOG_TAG, "defaultPermsWereGrantedSinceBoot(" + userId + ")");

            // Now call into the permission controller to apply policy around permissions
            final CountDownLatch latch = new CountDownLatch(1);

            // We need to create a local manager that does not schedule work on the main
            // there as we are on the main thread and want to block until the work is
            // completed or we time out.
            final PermissionControllerManager permissionControllerManager =
                    new PermissionControllerManager(
                            getUserContext(getContext(), UserHandle.of(userId)),
                            FgThread.getHandler());
            permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
                    FgThread.getExecutor(),
                    (Boolean success) -> {
                        if (!success) {
                            // We are in an undefined state now, let us crash and have
                            // rescue party suggest a wipe to recover to a good one.
                            final String message = "Error granting/upgrading runtime permissions";
                            Slog.wtf(LOG_TAG, message);
                            throw new IllegalStateException(message);
                        }
                        latch.countDown();
                    }
            );
            try {
                latch.await();
            } catch (InterruptedException e) {
                /* ignore */
            }

            packageManagerInternal.setRuntimePermissionsFingerPrint(Build.FINGERPRINT, userId);
        }
    }

    private static @Nullable Context getUserContext(@NonNull Context context,
            @Nullable UserHandle user) {
        if (context.getUser().equals(user)) {
            return context;
        } else {
            try {
                return context.createPackageContextAsUser(context.getPackageName(), 0, user);
            } catch (NameNotFoundException e) {
                Slog.e(LOG_TAG, "Cannot create context for user " + user, e);
                return null;
            }
        }
    }

    /**
     * Synchronize a single package.
     */
    private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
            @UserIdInt int userId) {
        synchronized (mLock) {
            mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
        }

        if (DEBUG) {
            Slog.v(LOG_TAG,
                    "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
                            + userId + ")");
        }

        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0,
                Process.SYSTEM_UID, userId);
        if (pkg == null) {
            return;
        }
        final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
                getUserContext(getContext(), UserHandle.of(userId)));
        synchroniser.addPackage(pkg.packageName);
        final String[] sharedPkgNames = packageManagerInternal.getPackagesForSharedUserId(
                pkg.sharedUserId, userId);
        if (sharedPkgNames != null) {
            for (String sharedPkgName : sharedPkgNames) {
                final PackageParser.Package sharedPkg = packageManagerInternal
                        .getPackage(sharedPkgName);
                if (sharedPkg != null) {
                    synchroniser.addPackage(sharedPkg.packageName);
                }
            }
        }
        synchroniser.syncPackages();
    }

    /**
     * Synchronize all packages
     */
    private void synchronizePermissionsAndAppOpsForUser(@UserIdInt int userId) {
        if (DEBUG) Slog.i(LOG_TAG, "synchronizePermissionsAndAppOpsForUser(" + userId + ")");

        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
                getUserContext(getContext(), UserHandle.of(userId)));
        packageManagerInternal.forEachPackage((pkg) -> synchronizer.addPackage(pkg.packageName));
        synchronizer.syncPackages();
    }

    /**
     * Synchronizes permission to app ops. You *must* always sync all packages
     * in a shared UID at the same time to ensure proper synchronization.
     */
    private static class PermissionToOpSynchroniser {
        private final @NonNull Context mContext;
        private final @NonNull PackageManager mPackageManager;
        private final @NonNull AppOpsManager mAppOpsManager;

        /** All uid that need to be synchronized */
        private final @NonNull SparseIntArray mAllUids = new SparseIntArray();

        /**
         * All ops that need to be set to default
         *
         * Currently, only used by the restricted permissions logic.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToDefault = new ArrayList<>();

        /**
         * All ops that need to be flipped to allow if default.
         *
         * Currently, only used by the restricted permissions logic.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToAllowIfDefault = new ArrayList<>();

        /**
         * All ops that need to be flipped to allow.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();

        /**
         * All ops that need to be flipped to ignore if default.
         *
         * Currently, only used by the restricted permissions logic.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfDefault = new ArrayList<>();

        /**
         * All ops that need to be flipped to ignore.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();

        /**
         * All ops that need to be flipped to foreground.
         *
         * Currently, only used by the foreground/background permissions logic.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();

        /**
         * All ops that need to be flipped to foreground if allow.
         *
         * Currently, only used by the foreground/background permissions logic.
         *
         * @see #syncPackages
         */
        private final @NonNull ArrayList<OpToChange> mOpsToForegroundIfAllow =
                new ArrayList<>();

        PermissionToOpSynchroniser(@NonNull Context context) {
            mContext = context;
            mPackageManager = context.getPackageManager();
            mAppOpsManager = context.getSystemService(AppOpsManager.class);
        }

        /**
         * Set app ops that were added in {@link #addPackage}.
         *
         * <p>This processes ops previously added by {@link #addOpIfRestricted}
         */
        private void syncPackages() {
            final int allowCount = mOpsToAllow.size();
            for (int i = 0; i < allowCount; i++) {
                final OpToChange op = mOpsToAllow.get(i);
                setUidModeAllowed(op.code, op.uid, op.packageName);
            }
            final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
            for (int i = 0; i < allowIfDefaultCount; i++) {
                final OpToChange op = mOpsToAllowIfDefault.get(i);
                setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
            }
            final int foregroundCount = mOpsToForegroundIfAllow.size();
            for (int i = 0; i < foregroundCount; i++) {
                final OpToChange op = mOpsToForegroundIfAllow.get(i);
                setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
            }
            final int foregroundIfAllowCount = mOpsToForeground.size();
            for (int i = 0; i < foregroundIfAllowCount; i++) {
                final OpToChange op = mOpsToForeground.get(i);
                setUidModeForeground(op.code, op.uid, op.packageName);
            }
            final int ignoreCount = mOpsToIgnore.size();
            for (int i = 0; i < ignoreCount; i++) {
                final OpToChange op = mOpsToIgnore.get(i);
                setUidModeIgnored(op.code, op.uid, op.packageName);
            }
            final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
            for (int i = 0; i < ignoreIfDefaultCount; i++) {
                final OpToChange op = mOpsToIgnoreIfDefault.get(i);
                setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
            }
            final int defaultCount = mOpsToDefault.size();
            for (int i = 0; i < defaultCount; i++) {
                final OpToChange op = mOpsToDefault.get(i);
                setUidModeDefault(op.code, op.uid, op.packageName);
            }
        }

        /**
         * Add op that belong to a restricted permission for later processing in
         * {@link #syncPackages()}.
         *
         * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
         *
         * @param permissionInfo The permission that is currently looked at
         * @param pkg The package looked at
         */
        private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo,
                @NonNull PackageInfo pkg) {
            final String permission = permissionInfo.name;
            final int opCode = AppOpsManager.permissionToOpCode(permission);
            final int uid = pkg.applicationInfo.uid;

            if (!permissionInfo.isRestricted()) {
                return;
            }

            final boolean applyRestriction =
                    (mPackageManager.getPermissionFlags(permission, pkg.packageName,
                    mContext.getUser()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;

            if (permissionInfo.isHardRestricted()) {
                if (opCode != OP_NONE) {
                    if (applyRestriction) {
                        mOpsToDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                    } else {
                        mOpsToAllowIfDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                    }
                }
            } else if (permissionInfo.isSoftRestricted()) {
                final SoftRestrictedPermissionPolicy policy =
                        SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.applicationInfo,
                                mContext.getUser(), permission);

                if (opCode != OP_NONE) {
                    if (policy.canBeGranted()) {
                        mOpsToAllowIfDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                    } else {
                        mOpsToDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                    }
                }

                final int op = policy.resolveAppOp();
                if (op != OP_NONE) {
                    switch (policy.getDesiredOpMode()) {
                        case MODE_DEFAULT:
                            mOpsToDefault.add(new OpToChange(uid, pkg.packageName, op));
                            break;
                        case MODE_ALLOWED:
                            if (policy.shouldSetAppOpIfNotDefault()) {
                                mOpsToAllow.add(new OpToChange(uid, pkg.packageName, op));
                            } else {
                                mOpsToAllowIfDefault.add(
                                        new OpToChange(uid, pkg.packageName, op));
                            }
                            break;
                        case MODE_FOREGROUND:
                            Slog.wtf(LOG_TAG,
                                    "Setting appop to foreground is not implemented");
                            break;
                        case MODE_IGNORED:
                            if (policy.shouldSetAppOpIfNotDefault()) {
                                mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, op));
                            } else {
                                mOpsToIgnoreIfDefault.add(
                                        new OpToChange(uid, pkg.packageName,
                                                op));
                            }
                            break;
                        case MODE_ERRORED:
                            Slog.wtf(LOG_TAG, "Setting appop to errored is not implemented");
                    }
                }
            }
        }

        private boolean isBgPermRestricted(@NonNull String pkg, @NonNull String perm, int uid) {
            try {
                final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(perm, 0);

                if (bgPermInfo.isSoftRestricted()) {
                    Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
                            + "implemented");
                }

                return bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
                                perm, pkg, UserHandle.getUserHandleForUid(uid))
                                & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
            } catch (NameNotFoundException e) {
                Slog.w(LOG_TAG, "Cannot read permission state of " + perm, e);
                return false;
            }
        }

        /**
         * Add op that belong to a foreground permission for later processing in
         * {@link #syncPackages()}.
         *
         * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
         *
         * @param permissionInfo The permission that is currently looked at
         * @param pkg The package looked at
         */
        private void addOpIfFgPermissions(@NonNull PermissionInfo permissionInfo,
                @NonNull PackageInfo pkg) {
            final String bgPermissionName = permissionInfo.backgroundPermission;

            if (bgPermissionName == null) {
                return;
            }

            final String permission = permissionInfo.name;
            final int opCode = AppOpsManager.permissionToOpCode(permission);
            final String pkgName = pkg.packageName;
            final int uid = pkg.applicationInfo.uid;

            // App does not support runtime permissions. Hence the state is encoded in the app-op.
            // To not override unrecoverable state don't change app-op unless bg perm is reviewed.
            if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
                // If the review is required for this permission, the grant state does not
                // really matter. To have a stable state, don't change the app-op if review is still
                // pending.
                int flags = mPackageManager.getPermissionFlags(bgPermissionName,
                        pkg.packageName, UserHandle.getUserHandleForUid(uid));

                if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
                        && isBgPermRestricted(pkgName, bgPermissionName, uid)) {
                    mOpsToForegroundIfAllow.add(new OpToChange(uid, pkgName, opCode));
                }

                return;
            }

            if (mPackageManager.checkPermission(permission, pkgName)
                    == PackageManager.PERMISSION_GRANTED) {
                final boolean isBgHardRestricted = isBgPermRestricted(pkgName, bgPermissionName,
                        uid);
                final boolean isBgPermGranted = mPackageManager.checkPermission(bgPermissionName,
                        pkgName) == PackageManager.PERMISSION_GRANTED;

                if (!isBgHardRestricted && isBgPermGranted) {
                    mOpsToAllow.add(new OpToChange(uid, pkgName, opCode));
                } else {
                    mOpsToForeground.add(new OpToChange(uid, pkgName, opCode));
                }
            } else {
                mOpsToIgnore.add(new OpToChange(uid, pkgName, opCode));
            }
        }

        /**
         * Add a package for {@link #syncPackages() processing} later.
         *
         * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
         *
         * @param pkgName The package to add for later processing.
         */
        void addPackage(@NonNull String pkgName) {
            final PackageInfo pkg;
            try {
                pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
            } catch (NameNotFoundException e) {
                return;
            }

            mAllUids.put(pkg.applicationInfo.uid, pkg.applicationInfo.uid);

            if (pkg.requestedPermissions == null) {
                return;
            }

            for (String permission : pkg.requestedPermissions) {
                final int opCode = AppOpsManager.permissionToOpCode(permission);
                if (opCode == OP_NONE) {
                    continue;
                }

                final PermissionInfo permissionInfo;
                try {
                    permissionInfo = mPackageManager.getPermissionInfo(permission, 0);
                } catch (PackageManager.NameNotFoundException e) {
                    continue;
                }

                addOpIfRestricted(permissionInfo, pkg);
                addOpIfFgPermissions(permissionInfo, pkg);
            }
        }

        private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
            setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
        }

        private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
            setUidMode(opCode, uid, MODE_ALLOWED, packageName);
        }

        private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
            setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
        }

        private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
            setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
        }

        private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
            setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
        }

        private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
            setUidMode(opCode, uid, MODE_IGNORED, packageName);
        }

        private void setUidMode(int opCode, int uid, int mode,
                @NonNull String packageName) {
            final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
                    .opToPublicName(opCode), uid, packageName);

            if (currentMode != mode) {
                mAppOpsManager.setUidMode(opCode, uid, mode);
            }
        }

        private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
                @NonNull String packageName) {
            final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
                    .opToPublicName(opCode), uid, packageName);

            if (currentMode == requiredModeBefore) {
                mAppOpsManager.setUidMode(opCode, uid, newMode);
            }
        }

        private void setUidModeDefault(int opCode, int uid, String packageName) {
            setUidMode(opCode, uid, MODE_DEFAULT, packageName);
        }

        private class OpToChange {
            final int uid;
            final @NonNull String packageName;
            final int code;

            OpToChange(int uid, @NonNull String packageName, int code) {
                this.uid = uid;
                this.packageName = packageName;
                this.code = code;
            }
        }
    }

    private class Internal extends PermissionPolicyInternal {

        @Override
        public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
                @Nullable String callingPackage) {
            if (callingPackage != null && isActionRemovedForCallingPackage(intent.getAction(),
                    callingPackage)) {
                Slog.w(LOG_TAG, "Action Removed: starting " + intent.toString() + " from "
                        + callingPackage + " (uid=" + callingUid + ")");
                return false;
            }
            return true;
        }

        /**
         * Check if the intent action is removed for the calling package (often based on target SDK
         * version). If the action is removed, we'll silently cancel the activity launch.
         */
        private boolean isActionRemovedForCallingPackage(@Nullable String action,
                @NonNull String callingPackage) {
            if (action == null) {
                return false;
            }
            switch (action) {
                case TelecomManager.ACTION_CHANGE_DEFAULT_DIALER:
                case Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT: {
                    ApplicationInfo applicationInfo;
                    try {
                        applicationInfo = getContext().getPackageManager().getApplicationInfo(
                                callingPackage, 0);
                    } catch (PackageManager.NameNotFoundException e) {
                        Slog.i(LOG_TAG, "Cannot find application info for " + callingPackage);
                        return false;
                    }
                    // Applications targeting Q should use RoleManager.createRequestRoleIntent()
                    // instead.
                    return applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
                }
                default:
                    return false;
            }
        }
    }
}
