Loading core/java/android/app/ForegroundServiceTypePolicy.java +117 −42 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -268,7 +271,8 @@ public abstract class ForegroundServiceTypePolicy { null /* allOfPermissions */, null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -284,7 +288,8 @@ public abstract class ForegroundServiceTypePolicy { null /* allOfPermissions */, null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -537,7 +553,8 @@ public abstract class ForegroundServiceTypePolicy { null /* allOfPermissions */, null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -555,7 +572,8 @@ public abstract class ForegroundServiceTypePolicy { }, true), null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -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 */ ); /** Loading Loading @@ -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. */ Loading Loading @@ -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. * Loading Loading @@ -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. */ Loading Loading @@ -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; Loading @@ -783,6 +837,7 @@ public abstract class ForegroundServiceTypePolicy { mPermissionEnforcementFlag = permissionEnforcementFlag; mPermissionEnforcementFlagDefaultValue = permissionEnforcementFlagDefaultValue; mPermissionEnforcementFlagValue = permissionEnforcementFlagDefaultValue; mForegroundOnlyPermission = foregroundOnlyPermission; } /** Loading Loading @@ -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. * Loading Loading @@ -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. Loading services/core/java/com/android/server/am/ActiveServices.java +8 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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: Loading Loading
core/java/android/app/ForegroundServiceTypePolicy.java +117 −42 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -268,7 +271,8 @@ public abstract class ForegroundServiceTypePolicy { null /* allOfPermissions */, null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -284,7 +288,8 @@ public abstract class ForegroundServiceTypePolicy { null /* allOfPermissions */, null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -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 */ ); /** Loading @@ -537,7 +553,8 @@ public abstract class ForegroundServiceTypePolicy { null /* allOfPermissions */, null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -555,7 +572,8 @@ public abstract class ForegroundServiceTypePolicy { }, true), null /* anyOfPermissions */, null /* permissionEnforcementFlag */, false /* permissionEnforcementFlagDefaultValue */ false /* permissionEnforcementFlagDefaultValue */, false /* foregroundOnlyPermission */ ); /** Loading @@ -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 */ ); /** Loading Loading @@ -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. */ Loading Loading @@ -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. * Loading Loading @@ -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. */ Loading Loading @@ -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; Loading @@ -783,6 +837,7 @@ public abstract class ForegroundServiceTypePolicy { mPermissionEnforcementFlag = permissionEnforcementFlag; mPermissionEnforcementFlagDefaultValue = permissionEnforcementFlagDefaultValue; mPermissionEnforcementFlagValue = permissionEnforcementFlagDefaultValue; mForegroundOnlyPermission = foregroundOnlyPermission; } /** Loading Loading @@ -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. * Loading Loading @@ -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. Loading
services/core/java/com/android/server/am/ActiveServices.java +8 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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: Loading