Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdee4a08 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Limit the background FGS start with foreground only permission" into udc-dev

parents 0dda4e11 efc41259
Loading
Loading
Loading
Loading
+117 −42
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app;

import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
@@ -37,6 +38,8 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESS
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED;
import static android.permission.PermissionCheckerManager.PERMISSION_HARD_DENIED;
import static android.permission.PermissionCheckerManager.PERMISSION_SOFT_DENIED;

import android.Manifest;
import android.annotation.IntDef;
@@ -268,7 +271,8 @@ public abstract class ForegroundServiceTypePolicy {
            null /* allOfPermissions */,
            null /* anyOfPermissions */,
            null /* permissionEnforcementFlag */,
            false /* permissionEnforcementFlagDefaultValue */
            false /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -284,7 +288,8 @@ public abstract class ForegroundServiceTypePolicy {
            null /* allOfPermissions */,
            null /* anyOfPermissions */,
            null /* permissionEnforcementFlag */,
            false /* permissionEnforcementFlagDefaultValue */
            false /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -302,7 +307,8 @@ public abstract class ForegroundServiceTypePolicy {
            }, true),
            null /* anyOfPermissions */,
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_DATA_SYNC /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -320,7 +326,8 @@ public abstract class ForegroundServiceTypePolicy {
            }, true),
            null /* anyOfPermissions */,
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_MEDIA_PLAYBACK /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -341,7 +348,8 @@ public abstract class ForegroundServiceTypePolicy {
                new RolePermission(RoleManager.ROLE_DIALER)
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PHONE_CALL /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -362,7 +370,8 @@ public abstract class ForegroundServiceTypePolicy {
                new RegularPermission(Manifest.permission.ACCESS_FINE_LOCATION),
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_LOCATION /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            true /* foregroundOnlyPermission */
    );

    /**
@@ -392,7 +401,8 @@ public abstract class ForegroundServiceTypePolicy {
                new UsbAccessoryPermission(),
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_CONNECTED_DEVICE /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -413,7 +423,8 @@ public abstract class ForegroundServiceTypePolicy {
                new AppOpPermission(AppOpsManager.OP_PROJECT_MEDIA)
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_MEDIA_PROJECTION /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -434,7 +445,8 @@ public abstract class ForegroundServiceTypePolicy {
                new RegularPermission(Manifest.permission.SYSTEM_CAMERA),
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_CAMERA /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            true /* foregroundOnlyPermission */
    );

    /**
@@ -459,7 +471,8 @@ public abstract class ForegroundServiceTypePolicy {
                new RegularPermission(Manifest.permission.RECORD_AUDIO),
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_MICROPHONE /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            true /* foregroundOnlyPermission */
    );

    /**
@@ -481,7 +494,8 @@ public abstract class ForegroundServiceTypePolicy {
                new RegularPermission(Manifest.permission.HIGH_SAMPLING_RATE_SENSORS),
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_HEALTH /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -499,7 +513,8 @@ public abstract class ForegroundServiceTypePolicy {
            }, true),
            null /* anyOfPermissions */,
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_REMOTE_MESSAGING /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -521,7 +536,8 @@ public abstract class ForegroundServiceTypePolicy {
                new AppOpPermission(AppOpsManager.OP_ACTIVATE_VPN),
            }, false),
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_SYSTEM_EXEMPTED /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -537,7 +553,8 @@ public abstract class ForegroundServiceTypePolicy {
            null /* allOfPermissions */,
            null /* anyOfPermissions */,
            null /* permissionEnforcementFlag */,
            false /* permissionEnforcementFlagDefaultValue */
            false /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -555,7 +572,8 @@ public abstract class ForegroundServiceTypePolicy {
            }, true),
            null /* anyOfPermissions */,
            null /* permissionEnforcementFlag */,
            false /* permissionEnforcementFlagDefaultValue */
            false /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -573,7 +591,8 @@ public abstract class ForegroundServiceTypePolicy {
            }, true),
            null /* anyOfPermissions */,
            FGS_TYPE_PERM_ENFORCEMENT_FLAG_SPECIAL_USE /* permissionEnforcementFlag */,
            true /* permissionEnforcementFlagDefaultValue */
            true /* permissionEnforcementFlagDefaultValue */,
            false /* foregroundOnlyPermission */
    );

    /**
@@ -640,6 +659,29 @@ public abstract class ForegroundServiceTypePolicy {
    @Retention(RetentionPolicy.SOURCE)
    public @interface ForegroundServicePolicyCheckCode{}

    /**
     * Whether or not to require that app to have actual access to certain foreground only
     * permissions before starting the foreground service.
     *
     * <p>
     * Examples here are microphone, camera and fg location related permissions.
     * When the user grants the permission, its permission state is set to "granted",
     * but the actual capability to access these sensors, is to be evaluated according to
     * its process state. The Android {@link android.os.Build.VERSION_CODES#R} introduced
     * the while-in-use permission, basically the background-started FGS will not have access
     * to these sensors. In this context, there is no legitimate reasons to start a FGS from
     * the background with these types. This flag controls the behavior of the enforcement,
     * when it's enabled, in the aforementioned case, the FGS start will result in
     * a SecurityException. </p>
     */
    private static final String FGS_TYPE_FG_PERM_ENFORCEMENT_FLAG =
            "fgs_type_fg_perm_enforcement_flag";

    /**
     * The default value to the {@link #FGS_TYPE_FG_PERM_ENFORCEMENT_FLAG}.
     */
    private static final boolean DEFAULT_FGS_TYPE_FG_PERM_ENFORCEMENT_FLAG_VALUE = true;

    /**
     * @return The policy info for the given type.
     */
@@ -682,6 +724,11 @@ public abstract class ForegroundServiceTypePolicy {
        }
    }

    private static boolean isFgsTypeFgPermissionEnforcementEnabled() {
        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                FGS_TYPE_FG_PERM_ENFORCEMENT_FLAG, DEFAULT_FGS_TYPE_FG_PERM_ENFORCEMENT_FLAG_VALUE);
    }

    /**
     * Constructor.
     *
@@ -738,6 +785,12 @@ public abstract class ForegroundServiceTypePolicy {
         */
        final boolean mPermissionEnforcementFlagDefaultValue;

        /**
         * Whether or not the permissions here are limited to foreground only.
         * Typical examples are microphone/camera/location.
         */
        final boolean mForegroundOnlyPermission;

        /**
         * A customized check for the permissions.
         */
@@ -774,7 +827,8 @@ public abstract class ForegroundServiceTypePolicy {
                @Nullable ForegroundServiceTypePermissions allOfPermissions,
                @Nullable ForegroundServiceTypePermissions anyOfPermissions,
                @Nullable String permissionEnforcementFlag,
                boolean permissionEnforcementFlagDefaultValue) {
                boolean permissionEnforcementFlagDefaultValue,
                boolean foregroundOnlyPermission) {
            mType = type;
            mDeprecationChangeId = deprecationChangeId;
            mDisabledChangeId = disabledChangeId;
@@ -783,6 +837,7 @@ public abstract class ForegroundServiceTypePolicy {
            mPermissionEnforcementFlag = permissionEnforcementFlag;
            mPermissionEnforcementFlagDefaultValue = permissionEnforcementFlagDefaultValue;
            mPermissionEnforcementFlagValue = permissionEnforcementFlagDefaultValue;
            mForegroundOnlyPermission = foregroundOnlyPermission;
        }

        /**
@@ -884,6 +939,14 @@ public abstract class ForegroundServiceTypePolicy {
                    && CompatChanges.isChangeEnabled(mDisabledChangeId, callerUid);
        }

        /**
         * Whether or not the permissions here are limited to foreground only.
         * Typical examples are microphone/camera/location.
         */
        public boolean hasForegroundOnlyPermission() {
            return mForegroundOnlyPermission;
        }

        /**
         * Override the type disabling change Id.
         *
@@ -1082,35 +1145,47 @@ public abstract class ForegroundServiceTypePolicy {
        @PackageManager.PermissionResult
        int checkPermission(@NonNull Context context, @NonNull String name, int callerUid,
                int callerPid, String packageName, boolean allowWhileInUse) {
            // Simple case, check if it's already granted.
            @PermissionCheckerManager.PermissionResult int result;
            if ((result = PermissionChecker.checkPermissionForPreflight(context, name, callerPid,
                    callerUid, packageName)) == PermissionCheckerManager.PERMISSION_GRANTED) {
                return PERMISSION_GRANTED;
            @PermissionCheckerManager.PermissionResult final int result =
                    PermissionChecker.checkPermissionForPreflight(context, name,
                            callerPid, callerUid, packageName);
            if (result == PERMISSION_HARD_DENIED) {
                // If the user didn't grant this permission at all.
                return PERMISSION_DENIED;
            }
            if (allowWhileInUse && result == PermissionCheckerManager.PERMISSION_SOFT_DENIED) {
                // Check its appops
            final int opCode = AppOpsManager.permissionToOpCode(name);
            if (opCode == AppOpsManager.OP_NONE) {
                // Simple case, check if it's already granted.
                return result == PermissionCheckerManager.PERMISSION_GRANTED
                        ? PERMISSION_GRANTED : PERMISSION_DENIED;
            }
            final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
                if (opCode != AppOpsManager.OP_NONE) {
                    final int currentMode = appOpsManager.unsafeCheckOpRawNoThrow(opCode, callerUid,
                            packageName);
                    if (currentMode == MODE_FOREGROUND) {
                        // It's in foreground only mode and we're allowing while-in-use.
            final int mode = appOpsManager.unsafeCheckOpRawNoThrow(opCode, callerUid, packageName);
            switch (mode) {
                case MODE_ALLOWED:
                    // The appop is just allowed, plain and simple.
                    return PERMISSION_GRANTED;
                    } else if (currentMode == MODE_IGNORED) {
                case MODE_DEFAULT:
                    // Follow the permission check result.
                    return result == PermissionCheckerManager.PERMISSION_GRANTED
                            ? PERMISSION_GRANTED : PERMISSION_DENIED;
                case MODE_FOREGROUND:
                    // If the enforcement flag is OFF, we silently allow it. Or, if it's in
                    // the foreground only mode and we're allowing while-in-use, allow it.
                    return !isFgsTypeFgPermissionEnforcementEnabled() || allowWhileInUse
                            ? PERMISSION_GRANTED : PERMISSION_DENIED;
                case MODE_IGNORED:
                    // If it's soft denied with the mode "ignore", semantically it's a silent
                    // failure and no exception should be thrown, we might not want to allow
                    // the FGS. However, since the user has agreed with this permission
                    // (otherwise it's going to be a hard denial), and we're allowing
                    // while-in-use here, it's safe to allow the FGS run here.
                        return PERMISSION_GRANTED;
                    }
                }
            }
                    return allowWhileInUse && result == PERMISSION_SOFT_DENIED
                            ? PERMISSION_GRANTED : PERMISSION_DENIED;
                default:
                    return PERMISSION_DENIED;
            }
        }
    }

    /**
     * This represents an app op permission to be required for a specific service type.
+8 −2
Original line number Diff line number Diff line
@@ -2667,7 +2667,10 @@ public final class ActiveServices {
                        + " code=" + code
                        + " callerApp=" + r.app
                        + " targetSDK=" + r.app.info.targetSdkVersion
                        + " requiredPermissions=" + policyInfo.toPermissionString();
                        + " requiredPermissions=" + policyInfo.toPermissionString()
                        + (policyInfo.hasForegroundOnlyPermission()
                        ? " and the app must be in the eligible state/exemptions"
                        + " to access the foreground only permission" : "");
                Slog.wtfQuiet(TAG, msg);
                Slog.w(TAG, msg);
            } break;
@@ -2677,7 +2680,10 @@ public final class ActiveServices {
                        + " callerApp=" + r.app
                        + " targetSDK=" + r.app.info.targetSdkVersion
                        + " requires permissions: "
                        + policyInfo.toPermissionString());
                        + policyInfo.toPermissionString()
                        + (policyInfo.hasForegroundOnlyPermission()
                        ? " and the app must be in the eligible state/exemptions"
                        + " to access the foreground only permission" : ""));
            } break;
            case FGS_TYPE_POLICY_CHECK_OK:
            default: