Implement the foreground service type enforcement
Currently it's warning only.
To test with it:
adb shell am compat enable FGS_TYPE_PERMISSION_CHANGE_ID \
com.my.package.name
adb shell am compat enable FGS_TYPE_DATA_SYNC_DISABLED_CHANGE_ID \
com.my.package.name
Bug: 246792057
Bug: 254662046
Test: atest CtsAppFgsTestCases
Change-Id: I87a112dc9f254e5ea3231bddaf7f542a19cb7604
This commit is contained in:
1033
core/java/android/app/ForegroundServiceTypePolicy.java
Normal file
1033
core/java/android/app/ForegroundServiceTypePolicy.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -495,6 +495,10 @@ applications that come with the platform
|
||||
<permission name="android.permission.READ_SAFETY_CENTER_STATUS" />
|
||||
<!-- Permission required for CTS test - CtsTelephonyTestCases -->
|
||||
<permission name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
|
||||
<!-- Permission required for CTS test - CtsAppTestCases -->
|
||||
<permission name="android.permission.CAPTURE_MEDIA_OUTPUT" />
|
||||
<permission name="android.permission.CAPTURE_TUNER_AUDIO_INPUT" />
|
||||
<permission name="android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT" />
|
||||
</privapp-permissions>
|
||||
|
||||
<privapp-permissions package="com.android.statementservice">
|
||||
|
||||
@@ -720,6 +720,57 @@
|
||||
<!-- Permission required for CTS test - CtsDeviceLockTestCases -->
|
||||
<uses-permission android:name="android.permission.MANAGE_DEVICE_LOCK_STATE" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
|
||||
|
||||
<!-- Permission required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
|
||||
<!-- Permissions required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.CAPTURE_MEDIA_OUTPUT" />
|
||||
|
||||
<!-- Permissions required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.CAPTURE_TUNER_AUDIO_INPUT" />
|
||||
|
||||
<!-- Permissions required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT" />
|
||||
|
||||
<!-- Permissions required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
|
||||
<!-- Permissions required for CTS test - CtsAppFgsTestCases -->
|
||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
|
||||
|
||||
<application android:label="@string/app_label"
|
||||
android:theme="@android:style/Theme.DeviceDefault.DayNight"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
|
||||
@@ -23,18 +23,29 @@ import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGRO
|
||||
import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_TOP;
|
||||
import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_DEPRECATED;
|
||||
import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_DISABLED;
|
||||
import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_OK;
|
||||
import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED;
|
||||
import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE;
|
||||
import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_UNKNOWN;
|
||||
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
|
||||
import static android.os.PowerExemptionManager.REASON_ACTIVE_DEVICE_ADMIN;
|
||||
import static android.os.PowerExemptionManager.REASON_ACTIVITY_STARTER;
|
||||
import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD;
|
||||
import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
|
||||
import static android.os.PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
|
||||
import static android.os.PowerExemptionManager.REASON_BACKGROUND_FGS_PERMISSION;
|
||||
import static android.os.PowerExemptionManager.REASON_CARRIER_PRIVILEGED_APP;
|
||||
import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
|
||||
import static android.os.PowerExemptionManager.REASON_CURRENT_INPUT_METHOD;
|
||||
import static android.os.PowerExemptionManager.REASON_DENIED;
|
||||
import static android.os.PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
|
||||
import static android.os.PowerExemptionManager.REASON_DEVICE_OWNER;
|
||||
import static android.os.PowerExemptionManager.REASON_DISALLOW_APPS_CONTROL;
|
||||
import static android.os.PowerExemptionManager.REASON_DPO_PROTECTED_APP;
|
||||
import static android.os.PowerExemptionManager.REASON_FGS_BINDING;
|
||||
import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
|
||||
import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
|
||||
@@ -45,10 +56,12 @@ import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
|
||||
import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
|
||||
import static android.os.PowerExemptionManager.REASON_PROC_STATE_TOP;
|
||||
import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER;
|
||||
import static android.os.PowerExemptionManager.REASON_ROLE_EMERGENCY;
|
||||
import static android.os.PowerExemptionManager.REASON_SERVICE_LAUNCH;
|
||||
import static android.os.PowerExemptionManager.REASON_START_ACTIVITY_FLAG;
|
||||
import static android.os.PowerExemptionManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
|
||||
import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
|
||||
import static android.os.PowerExemptionManager.REASON_SYSTEM_MODULE;
|
||||
import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
|
||||
import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE;
|
||||
import static android.os.PowerExemptionManager.REASON_UID_VISIBLE;
|
||||
@@ -63,6 +76,9 @@ import static android.os.Process.SYSTEM_UID;
|
||||
import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
|
||||
|
||||
import static com.android.internal.messages.nano.SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICE_BG_LAUNCH;
|
||||
import static com.android.internal.util.FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED;
|
||||
import static com.android.internal.util.FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER;
|
||||
import static com.android.internal.util.FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT;
|
||||
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED;
|
||||
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
|
||||
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT;
|
||||
@@ -94,6 +110,11 @@ import android.app.ActivityThread;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.ForegroundServiceStartNotAllowedException;
|
||||
import android.app.ForegroundServiceTypeNotAllowedException;
|
||||
import android.app.ForegroundServiceTypePolicy;
|
||||
import android.app.ForegroundServiceTypePolicy.ForegroundServicePolicyCheckCode;
|
||||
import android.app.ForegroundServiceTypePolicy.ForegroundServiceTypePermission;
|
||||
import android.app.ForegroundServiceTypePolicy.ForegroundServiceTypePolicyInfo;
|
||||
import android.app.IApplicationThread;
|
||||
import android.app.IForegroundServiceObserver;
|
||||
import android.app.IServiceConnection;
|
||||
@@ -122,6 +143,7 @@ import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.ServiceInfo.ForegroundServiceType;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
@@ -576,6 +598,7 @@ public final class ActiveServices {
|
||||
getAppStateTracker().addBackgroundRestrictedAppListener(new BackgroundRestrictedListener());
|
||||
mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class);
|
||||
setAllowListWhileInUsePermissionInFgs();
|
||||
initSystemExemptedFgsTypePermission();
|
||||
}
|
||||
|
||||
private AppStateTracker getAppStateTracker() {
|
||||
@@ -757,8 +780,8 @@ public final class ActiveServices {
|
||||
Slog.w(TAG, msg);
|
||||
showFgsBgRestrictedNotificationLocked(r);
|
||||
logFGSStateChangeLocked(r,
|
||||
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
|
||||
0, FGS_STOP_REASON_UNKNOWN);
|
||||
FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
|
||||
0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
|
||||
if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID, callingUid)) {
|
||||
throw new ForegroundServiceStartNotAllowedException(msg);
|
||||
}
|
||||
@@ -1911,6 +1934,7 @@ public final class ActiveServices {
|
||||
ignoreForeground = true;
|
||||
}
|
||||
|
||||
int fgsTypeCheckCode = FGS_TYPE_POLICY_CHECK_UNKNOWN;
|
||||
if (!ignoreForeground) {
|
||||
if (r.mStartForegroundCount == 0) {
|
||||
/*
|
||||
@@ -1969,13 +1993,49 @@ public final class ActiveServices {
|
||||
updateServiceForegroundLocked(psr, true);
|
||||
ignoreForeground = true;
|
||||
logFGSStateChangeLocked(r,
|
||||
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
|
||||
0, FGS_STOP_REASON_UNKNOWN);
|
||||
FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
|
||||
0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
|
||||
if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID,
|
||||
r.appInfo.uid)) {
|
||||
throw new ForegroundServiceStartNotAllowedException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreForeground) {
|
||||
Pair<Integer, RuntimeException> fgsTypeResult = null;
|
||||
if (foregroundServiceType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
|
||||
fgsTypeResult = validateForegroundServiceType(r,
|
||||
foregroundServiceType,
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
|
||||
} else {
|
||||
int fgsTypes = foregroundServiceType;
|
||||
// If the service has declared some unknown types which might be coming
|
||||
// from future releases, and if it also comes with the "specialUse",
|
||||
// then it'll be deemed as the "specialUse" and we ignore this
|
||||
// unknown type. Otherwise, it'll be treated as an invalid type.
|
||||
int defaultFgsTypes = (foregroundServiceType
|
||||
& ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE) != 0
|
||||
? ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
||||
: ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
|
||||
for (int serviceType = Integer.highestOneBit(fgsTypes);
|
||||
serviceType != 0;
|
||||
serviceType = Integer.highestOneBit(fgsTypes)) {
|
||||
fgsTypeResult = validateForegroundServiceType(r,
|
||||
serviceType, defaultFgsTypes);
|
||||
fgsTypes &= ~serviceType;
|
||||
if (fgsTypeResult.first != FGS_TYPE_POLICY_CHECK_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fgsTypeCheckCode = fgsTypeResult.first;
|
||||
if (fgsTypeResult.second != null) {
|
||||
logFGSStateChangeLocked(r,
|
||||
FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
|
||||
0, FGS_STOP_REASON_UNKNOWN, fgsTypeResult.first);
|
||||
throw fgsTypeResult.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apps under strict background restrictions simply don't get to have foreground
|
||||
@@ -2044,8 +2104,8 @@ public final class ActiveServices {
|
||||
registerAppOpCallbackLocked(r);
|
||||
mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
|
||||
logFGSStateChangeLocked(r,
|
||||
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
|
||||
0, FGS_STOP_REASON_UNKNOWN);
|
||||
FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
|
||||
0, FGS_STOP_REASON_UNKNOWN, fgsTypeCheckCode);
|
||||
updateNumForegroundServicesLocked();
|
||||
}
|
||||
// Even if the service is already a FGS, we need to update the notification,
|
||||
@@ -2126,10 +2186,11 @@ public final class ActiveServices {
|
||||
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
|
||||
unregisterAppOpCallbackLocked(r);
|
||||
logFGSStateChangeLocked(r,
|
||||
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
|
||||
FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
|
||||
r.mFgsExitTime > r.mFgsEnterTime
|
||||
? (int) (r.mFgsExitTime - r.mFgsEnterTime) : 0,
|
||||
FGS_STOP_REASON_STOP_FOREGROUND);
|
||||
FGS_STOP_REASON_STOP_FOREGROUND,
|
||||
FGS_TYPE_POLICY_CHECK_UNKNOWN);
|
||||
r.mFgsNotificationWasDeferred = false;
|
||||
signalForegroundServiceObserversLocked(r);
|
||||
resetFgsRestrictionLocked(r);
|
||||
@@ -2165,6 +2226,118 @@ public final class ActiveServices {
|
||||
return now < eligible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the given service can start a foreground service with given type.
|
||||
*
|
||||
* @return A pair, where the first parameter is the result code and second is the exception
|
||||
* object if it fails to start a foreground service with given type.
|
||||
*/
|
||||
@NonNull
|
||||
private Pair<Integer, RuntimeException> validateForegroundServiceType(ServiceRecord r,
|
||||
@ForegroundServiceType int type,
|
||||
@ForegroundServiceType int defaultToType) {
|
||||
final ForegroundServiceTypePolicy policy = ForegroundServiceTypePolicy.getDefaultPolicy();
|
||||
final ForegroundServiceTypePolicyInfo policyInfo =
|
||||
policy.getForegroundServiceTypePolicyInfo(type, defaultToType);
|
||||
final @ForegroundServicePolicyCheckCode int code = policy.checkForegroundServiceTypePolicy(
|
||||
mAm.mContext, r.packageName, r.app.uid, r.app.getPid(),
|
||||
r.mAllowWhileInUsePermissionInFgs, policyInfo);
|
||||
RuntimeException exception = null;
|
||||
switch (code) {
|
||||
case FGS_TYPE_POLICY_CHECK_DEPRECATED: {
|
||||
final String msg = "Starting FGS with type "
|
||||
+ ServiceInfo.foregroundServiceTypeToLabel(type)
|
||||
+ " code=" + code
|
||||
+ " callerApp=" + r.app
|
||||
+ " targetSDK=" + r.app.info.targetSdkVersion;
|
||||
Slog.wtfQuiet(TAG, msg);
|
||||
Slog.w(TAG, msg);
|
||||
} break;
|
||||
case FGS_TYPE_POLICY_CHECK_DISABLED: {
|
||||
exception = new ForegroundServiceTypeNotAllowedException(
|
||||
"Starting FGS with type "
|
||||
+ ServiceInfo.foregroundServiceTypeToLabel(type)
|
||||
+ " callerApp=" + r.app
|
||||
+ " targetSDK=" + r.app.info.targetSdkVersion
|
||||
+ " has been prohibited");
|
||||
} break;
|
||||
case FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE: {
|
||||
final String msg = "Starting FGS with type "
|
||||
+ ServiceInfo.foregroundServiceTypeToLabel(type)
|
||||
+ " code=" + code
|
||||
+ " callerApp=" + r.app
|
||||
+ " targetSDK=" + r.app.info.targetSdkVersion
|
||||
+ " requiredPermissions=" + policyInfo.toPermissionString();
|
||||
Slog.wtfQuiet(TAG, msg);
|
||||
Slog.w(TAG, msg);
|
||||
} break;
|
||||
case FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED: {
|
||||
exception = new SecurityException("Starting FGS with type "
|
||||
+ ServiceInfo.foregroundServiceTypeToLabel(type)
|
||||
+ " callerApp=" + r.app
|
||||
+ " targetSDK=" + r.app.info.targetSdkVersion
|
||||
+ " requires permissions: "
|
||||
+ policyInfo.toPermissionString());
|
||||
} break;
|
||||
case FGS_TYPE_POLICY_CHECK_OK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Pair.create(code, exception);
|
||||
}
|
||||
|
||||
private class SystemExemptedFgsTypePermission extends ForegroundServiceTypePermission {
|
||||
SystemExemptedFgsTypePermission() {
|
||||
super("System exempted");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkPermission(@NonNull Context context, int callerUid, int callerPid,
|
||||
@NonNull String packageName, boolean allowWhileInUse) {
|
||||
final AppRestrictionController appRestrictionController = mAm.mAppRestrictionController;
|
||||
@ReasonCode int reason = appRestrictionController
|
||||
.getPotentialSystemExemptionReason(callerUid);
|
||||
if (reason == REASON_DENIED) {
|
||||
reason = appRestrictionController
|
||||
.getPotentialSystemExemptionReason(callerUid, packageName);
|
||||
if (reason == REASON_DENIED) {
|
||||
reason = appRestrictionController
|
||||
.getPotentialUserAllowedExemptionReason(callerUid, packageName);
|
||||
}
|
||||
}
|
||||
switch (reason) {
|
||||
case REASON_SYSTEM_UID:
|
||||
case REASON_SYSTEM_ALLOW_LISTED:
|
||||
case REASON_DEVICE_DEMO_MODE:
|
||||
case REASON_DISALLOW_APPS_CONTROL:
|
||||
case REASON_DEVICE_OWNER:
|
||||
case REASON_PROFILE_OWNER:
|
||||
case REASON_PROC_STATE_PERSISTENT:
|
||||
case REASON_PROC_STATE_PERSISTENT_UI:
|
||||
case REASON_SYSTEM_MODULE:
|
||||
case REASON_CARRIER_PRIVILEGED_APP:
|
||||
case REASON_DPO_PROTECTED_APP:
|
||||
case REASON_ACTIVE_DEVICE_ADMIN:
|
||||
case REASON_ROLE_EMERGENCY:
|
||||
case REASON_ALLOWLISTED_PACKAGE:
|
||||
return PERMISSION_GRANTED;
|
||||
default:
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initSystemExemptedFgsTypePermission() {
|
||||
final ForegroundServiceTypePolicy policy = ForegroundServiceTypePolicy.getDefaultPolicy();
|
||||
final ForegroundServiceTypePolicyInfo policyInfo =
|
||||
policy.getForegroundServiceTypePolicyInfo(
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED,
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
|
||||
if (policyInfo != null) {
|
||||
policyInfo.setCustomPermission(new SystemExemptedFgsTypePermission());
|
||||
}
|
||||
}
|
||||
|
||||
ServiceNotificationPolicy applyForegroundServiceNotificationLocked(Notification notification,
|
||||
final String tag, final int id, final String pkg, final int userId) {
|
||||
// By nature of the FGS API, all FGS notifications have a null tag
|
||||
@@ -4777,10 +4950,11 @@ public final class ActiveServices {
|
||||
unregisterAppOpCallbackLocked(r);
|
||||
r.mFgsExitTime = SystemClock.uptimeMillis();
|
||||
logFGSStateChangeLocked(r,
|
||||
FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
|
||||
FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
|
||||
r.mFgsExitTime > r.mFgsEnterTime
|
||||
? (int) (r.mFgsExitTime - r.mFgsEnterTime) : 0,
|
||||
FGS_STOP_REASON_STOP_SERVICE);
|
||||
FGS_STOP_REASON_STOP_SERVICE,
|
||||
FGS_TYPE_POLICY_CHECK_UNKNOWN);
|
||||
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
|
||||
}
|
||||
|
||||
@@ -7020,17 +7194,20 @@ public final class ActiveServices {
|
||||
* @param r ServiceRecord
|
||||
* @param state one of ENTER/EXIT/DENIED event.
|
||||
* @param durationMs Only meaningful for EXIT event, the duration from ENTER and EXIT state.
|
||||
* @param fgsStopReason why was this FGS stopped.
|
||||
* @param fgsTypeCheckCode The FGS type policy check result.
|
||||
*/
|
||||
private void logFGSStateChangeLocked(ServiceRecord r, int state, int durationMs,
|
||||
@FgsStopReason int fgsStopReason) {
|
||||
@FgsStopReason int fgsStopReason,
|
||||
@ForegroundServicePolicyCheckCode int fgsTypeCheckCode) {
|
||||
if (!ActivityManagerUtils.shouldSamplePackageForAtom(
|
||||
r.packageName, mAm.mConstants.mFgsAtomSampleRate)) {
|
||||
return;
|
||||
}
|
||||
boolean allowWhileInUsePermissionInFgs;
|
||||
@PowerExemptionManager.ReasonCode int fgsStartReasonCode;
|
||||
if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER
|
||||
|| state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
|
||||
if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER
|
||||
|| state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
|
||||
allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering;
|
||||
fgsStartReasonCode = r.mAllowStartForegroundAtEntering;
|
||||
} else {
|
||||
@@ -7056,14 +7233,15 @@ public final class ActiveServices {
|
||||
r.mStartForegroundCount,
|
||||
ActivityManagerUtils.hashComponentNameForAtom(r.shortInstanceName),
|
||||
r.mFgsHasNotificationPermission,
|
||||
r.foregroundServiceType);
|
||||
r.foregroundServiceType,
|
||||
fgsTypeCheckCode);
|
||||
|
||||
int event = 0;
|
||||
if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
|
||||
if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
|
||||
event = EventLogTags.AM_FOREGROUND_SERVICE_START;
|
||||
} else if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
|
||||
} else if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
|
||||
event = EventLogTags.AM_FOREGROUND_SERVICE_STOP;
|
||||
} else if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED) {
|
||||
} else if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED) {
|
||||
event = EventLogTags.AM_FOREGROUND_SERVICE_DENIED;
|
||||
} else {
|
||||
// Unknown event.
|
||||
|
||||
@@ -2784,6 +2784,37 @@ public final class AppRestrictionController {
|
||||
*/
|
||||
@ReasonCode
|
||||
int getBackgroundRestrictionExemptionReason(int uid) {
|
||||
@ReasonCode int reason = getPotentialSystemExemptionReason(uid);
|
||||
if (reason != REASON_DENIED) {
|
||||
return reason;
|
||||
}
|
||||
final String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
|
||||
if (packages != null) {
|
||||
// Check each packages to see if any of them is in the "fixed" exemption cases.
|
||||
for (String pkg : packages) {
|
||||
reason = getPotentialSystemExemptionReason(uid, pkg);
|
||||
if (reason != REASON_DENIED) {
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
// Loop the packages again, and check the user-configurable exemptions.
|
||||
for (String pkg : packages) {
|
||||
reason = getPotentialUserAllowedExemptionReason(uid, pkg);
|
||||
if (reason != REASON_DENIED) {
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
}
|
||||
return REASON_DENIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uid The uid to check.
|
||||
* @return The potential exemption reason of the given uid. The caller must decide
|
||||
* whether or not it should be exempted.
|
||||
*/
|
||||
@ReasonCode
|
||||
int getPotentialSystemExemptionReason(int uid) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return REASON_SYSTEM_UID;
|
||||
}
|
||||
@@ -2811,37 +2842,51 @@ public final class AppRestrictionController {
|
||||
} else if (uidProcState <= PROCESS_STATE_PERSISTENT_UI) {
|
||||
return REASON_PROC_STATE_PERSISTENT_UI;
|
||||
}
|
||||
final String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
|
||||
if (packages != null) {
|
||||
final AppOpsManager appOpsManager = mInjector.getAppOpsManager();
|
||||
final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
|
||||
final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
|
||||
// Check each packages to see if any of them is in the "fixed" exemption cases.
|
||||
for (String pkg : packages) {
|
||||
if (isSystemModule(pkg)) {
|
||||
return REASON_SYSTEM_MODULE;
|
||||
} else if (isCarrierApp(pkg)) {
|
||||
return REASON_CARRIER_PRIVILEGED_APP;
|
||||
} else if (isExemptedFromSysConfig(pkg)) {
|
||||
return REASON_SYSTEM_ALLOW_LISTED;
|
||||
} else if (mConstantsObserver.mBgRestrictionExemptedPackages.contains(pkg)) {
|
||||
return REASON_SYSTEM_ALLOW_LISTED;
|
||||
} else if (pm.isPackageStateProtected(pkg, userId)) {
|
||||
return REASON_DPO_PROTECTED_APP;
|
||||
} else if (appStandbyInternal.isActiveDeviceAdmin(pkg, userId)) {
|
||||
return REASON_ACTIVE_DEVICE_ADMIN;
|
||||
}
|
||||
}
|
||||
// Loop the packages again, and check the user-configurable exemptions.
|
||||
for (String pkg : packages) {
|
||||
if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
|
||||
uid, pkg) == AppOpsManager.MODE_ALLOWED) {
|
||||
return REASON_OP_ACTIVATE_VPN;
|
||||
} else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
|
||||
uid, pkg) == AppOpsManager.MODE_ALLOWED) {
|
||||
return REASON_OP_ACTIVATE_PLATFORM_VPN;
|
||||
}
|
||||
}
|
||||
return REASON_DENIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uid The uid to check.
|
||||
* @param pkgName The package name to check.
|
||||
* @return The potential system-fixed exemption reason of the given uid/package. The caller
|
||||
* must decide whether or not it should be exempted.
|
||||
*/
|
||||
@ReasonCode
|
||||
int getPotentialSystemExemptionReason(int uid, String pkg) {
|
||||
final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
|
||||
final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
if (isSystemModule(pkg)) {
|
||||
return REASON_SYSTEM_MODULE;
|
||||
} else if (isCarrierApp(pkg)) {
|
||||
return REASON_CARRIER_PRIVILEGED_APP;
|
||||
} else if (isExemptedFromSysConfig(pkg)) {
|
||||
return REASON_SYSTEM_ALLOW_LISTED;
|
||||
} else if (mConstantsObserver.mBgRestrictionExemptedPackages.contains(pkg)) {
|
||||
return REASON_SYSTEM_ALLOW_LISTED;
|
||||
} else if (pm.isPackageStateProtected(pkg, userId)) {
|
||||
return REASON_DPO_PROTECTED_APP;
|
||||
} else if (appStandbyInternal.isActiveDeviceAdmin(pkg, userId)) {
|
||||
return REASON_ACTIVE_DEVICE_ADMIN;
|
||||
}
|
||||
return REASON_DENIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uid The uid to check.
|
||||
* @param pkgName The package name to check.
|
||||
* @return The potential user-allowed exemption reason of the given uid/package. The caller
|
||||
* must decide whether or not it should be exempted.
|
||||
*/
|
||||
@ReasonCode
|
||||
int getPotentialUserAllowedExemptionReason(int uid, String pkg) {
|
||||
final AppOpsManager appOpsManager = mInjector.getAppOpsManager();
|
||||
if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
|
||||
uid, pkg) == AppOpsManager.MODE_ALLOWED) {
|
||||
return REASON_OP_ACTIVATE_VPN;
|
||||
} else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
|
||||
uid, pkg) == AppOpsManager.MODE_ALLOWED) {
|
||||
return REASON_OP_ACTIVATE_PLATFORM_VPN;
|
||||
}
|
||||
if (isRoleHeldByUid(RoleManager.ROLE_DIALER, uid)) {
|
||||
return REASON_ROLE_DIALER;
|
||||
@@ -2852,6 +2897,7 @@ public final class AppRestrictionController {
|
||||
if (isOnDeviceIdleAllowlist(uid)) {
|
||||
return REASON_ALLOWLISTED_PACKAGE;
|
||||
}
|
||||
final ActivityManagerInternal am = mInjector.getActivityManagerInternal();
|
||||
if (am.isAssociatedCompanionApp(UserHandle.getUserId(uid), uid)) {
|
||||
return REASON_COMPANION_DEVICE_MANAGER;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user