diff options
| author | 2020-11-10 17:27:21 +0000 | |
|---|---|---|
| committer | 2020-11-10 17:27:21 +0000 | |
| commit | 32026d51a17455ef449a67bf75d7990bf118380a (patch) | |
| tree | 29e15111ae46e9ff8b52bd68d46b5fa337a08821 | |
| parent | b73cc69fbc8a18f94342e972f9ae42e2b85f1a32 (diff) | |
| parent | 859ba0692a48d7dd22b6e071d327113f13e0211d (diff) | |
Merge "Allow FGS start for proc state BOUND_FOREGROUND_SERVICE and above."
3 files changed, 107 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 4a338b37e41f..e1124ab50a39 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -17,6 +17,7 @@ package com.android.server.am; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; +import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; import static android.os.Process.NFC_UID; @@ -145,7 +146,7 @@ public final class ActiveServices { private static final boolean SHOW_DUNGEON_NOTIFICATION = false; public static final int FGS_FEATURE_DENIED = 0; - public static final int FGS_FEATURE_ALLOWED_BY_PROC_STATE = 1; + public static final int FGS_FEATURE_ALLOWED_BY_UID_STATE = 1; public static final int FGS_FEATURE_ALLOWED_BY_UID_VISIBLE = 2; public static final int FGS_FEATURE_ALLOWED_BY_FLAG = 3; public static final int FGS_FEATURE_ALLOWED_BY_SYSTEM_UID = 4; @@ -154,10 +155,12 @@ public final class ActiveServices { public static final int FGS_FEATURE_ALLOWED_BY_PERMISSION = 7; public static final int FGS_FEATURE_ALLOWED_BY_WHITELIST = 8; public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER = 9; + public static final int FGS_FEATURE_ALLOWED_BY_PROC_STATE = 10; + public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST = 11; @IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = { FGS_FEATURE_DENIED, - FGS_FEATURE_ALLOWED_BY_PROC_STATE, + FGS_FEATURE_ALLOWED_BY_UID_STATE, FGS_FEATURE_ALLOWED_BY_UID_VISIBLE, FGS_FEATURE_ALLOWED_BY_FLAG, FGS_FEATURE_ALLOWED_BY_SYSTEM_UID, @@ -165,7 +168,9 @@ public final class ActiveServices { FGS_FEATURE_ALLOWED_BY_TOKEN, FGS_FEATURE_ALLOWED_BY_PERMISSION, FGS_FEATURE_ALLOWED_BY_WHITELIST, - FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER + FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER, + FGS_FEATURE_ALLOWED_BY_PROC_STATE, + FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST }) @Retention(RetentionPolicy.SOURCE) public @interface FgsFeatureRetCode {} @@ -576,18 +581,11 @@ public final class ActiveServices { if (r.mAllowStartForeground == FGS_FEATURE_DENIED && (mAm.mConstants.mFlagFgsStartRestrictionEnabled || isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r))) { - if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled - && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { - // uid is on DeviceIdleController's allowlist. - Slog.d(TAG, "startForegroundService() mAllowStartForeground false " - + "but allowlist true: service " + r.shortInstanceName); - } else { - Slog.w(TAG, "startForegroundService() not allowed due to " - + "mAllowStartForeground false: service " - + r.shortInstanceName); - showFgsBgRestrictedNotificationLocked(r); - return null; - } + Slog.w(TAG, "startForegroundService() not allowed due to " + + "mAllowStartForeground false: service " + + r.shortInstanceName); + showFgsBgRestrictedNotificationLocked(r); + return null; } } } @@ -1488,20 +1486,12 @@ public final class ActiveServices { if (r.mAllowStartForeground == FGS_FEATURE_DENIED && (mAm.mConstants.mFlagFgsStartRestrictionEnabled || isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r))) { - if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled - && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { - // uid is on DeviceIdleController's allowlist. - Slog.d(TAG, "Service.startForeground() " - + "mAllowStartForeground false but allowlist true: service " - + r.shortInstanceName); - } else { - Slog.w(TAG, "Service.startForeground() not allowed due to " - + "mAllowStartForeground false: service " - + r.shortInstanceName); - showFgsBgRestrictedNotificationLocked(r); - updateServiceForegroundLocked(r.app, true); - ignoreForeground = true; - } + Slog.w(TAG, "Service.startForeground() not allowed due to " + + "mAllowStartForeground false: service " + + r.shortInstanceName); + showFgsBgRestrictedNotificationLocked(r); + updateServiceForegroundLocked(r.app, true); + ignoreForeground = true; } } } @@ -4944,38 +4934,39 @@ public final class ActiveServices { r.mAllowWhileInUsePermissionInFgs = true; } - if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == FGS_FEATURE_DENIED)) { - final @FgsFeatureRetCode int temp = shouldAllowFgsFeatureLocked(callingPackage, - callingPid, callingUid, intent, r, allowBackgroundActivityStarts); + if (!r.mAllowWhileInUsePermissionInFgs + || (r.mAllowStartForeground == FGS_FEATURE_DENIED)) { + final @FgsFeatureRetCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( + callingPackage, callingPid, callingUid, r, allowBackgroundActivityStarts); if (!r.mAllowWhileInUsePermissionInFgs) { - r.mAllowWhileInUsePermissionInFgs = (temp != FGS_FEATURE_DENIED); + r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != FGS_FEATURE_DENIED); } if (r.mAllowStartForeground == FGS_FEATURE_DENIED) { - r.mAllowStartForeground = temp; + r.mAllowStartForeground = shouldAllowFgsStartForegroundLocked(allowWhileInUse, + callingPackage, callingPid, callingUid, intent, r, + allowBackgroundActivityStarts); } } } /** - * Should allow FGS feature or not. + * Should allow while-in-use permissions in FGS or not. + * A typical BG started FGS is not allowed to have while-in-use permissions. * @param callingPackage caller app's package name. * @param callingUid caller app's uid. - * @param intent intent to start/bind service. * @param r the service to start. * @return {@link FgsFeatureRetCode} */ - private @FgsFeatureRetCode int shouldAllowFgsFeatureLocked(String callingPackage, - int callingPid, int callingUid, Intent intent, ServiceRecord r, + private @FgsFeatureRetCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage, + int callingPid, int callingUid, ServiceRecord r, boolean allowBackgroundActivityStarts) { int ret = FGS_FEATURE_DENIED; - final StringBuilder sb = new StringBuilder(64); final int uidState = mAm.getUidState(callingUid); if (ret == FGS_FEATURE_DENIED) { // Is the calling UID at PROCESS_STATE_TOP or above? if (uidState <= ActivityManager.PROCESS_STATE_TOP) { - sb.append("uidState=").append(uidState); - ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE; + ret = FGS_FEATURE_ALLOWED_BY_UID_STATE; } } @@ -5010,7 +5001,6 @@ public final class ActiveServices { } if (isCallerSystem) { - sb.append("callingUid=").append(callingAppId); ret = FGS_FEATURE_ALLOWED_BY_SYSTEM_UID; } } @@ -5049,6 +5039,53 @@ public final class ActiveServices { ret = FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER; } } + return ret; + } + + /** + * Should allow the FGS to start (AKA startForeground()) or not. + * The check in this method is in addition to check in + * {@link #shouldAllowFgsWhileInUsePermissionLocked} + * @param allowWhileInUse the return code from {@link #shouldAllowFgsWhileInUsePermissionLocked} + * @param callingPackage caller app's package name. + * @param callingUid caller app's uid. + * @param intent intent to start/bind service. + * @param r the service to start. + * @return {@link FgsFeatureRetCode} + */ + private @FgsFeatureRetCode int shouldAllowFgsStartForegroundLocked( + @FgsFeatureRetCode int allowWhileInUse, String callingPackage, int callingPid, + int callingUid, Intent intent, ServiceRecord r, boolean allowBackgroundActivityStarts) { + int ret = allowWhileInUse; + + final StringBuilder sb = new StringBuilder(64); + final int uidState = mAm.getUidState(callingUid); + if (ret == FGS_FEATURE_DENIED) { + // Is the calling UID at PROCESS_STATE_TOP or above? + if (uidState <= ActivityManager.PROCESS_STATE_TOP) { + sb.append("uidState=").append(uidState); + ret = FGS_FEATURE_ALLOWED_BY_UID_STATE; + } + } + + if (ret == FGS_FEATURE_DENIED) { + for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) { + final ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i); + if (pr.uid == callingUid + && pr.mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { + ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE; + break; + } + } + } + + if (ret == FGS_FEATURE_DENIED) { + if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled + && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { + // uid is on DeviceIdleController's allowlist. + ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST; + } + } final String debugInfo = "[callingPackage: " + callingPackage @@ -5071,8 +5108,8 @@ public final class ActiveServices { switch (code) { case FGS_FEATURE_DENIED: return "DENIED"; - case FGS_FEATURE_ALLOWED_BY_PROC_STATE: - return "ALLOWED_BY_PROC_STATE"; + case FGS_FEATURE_ALLOWED_BY_UID_STATE: + return "ALLOWED_BY_UID_STATE"; case FGS_FEATURE_ALLOWED_BY_UID_VISIBLE: return "ALLOWED_BY_UID_VISIBLE"; case FGS_FEATURE_ALLOWED_BY_FLAG: @@ -5089,13 +5126,17 @@ public final class ActiveServices { return "ALLOWED_BY_WHITELIST"; case FGS_FEATURE_ALLOWED_BY_DEVICE_OWNER: return "ALLOWED_BY_DEVICE_OWNER"; + case FGS_FEATURE_ALLOWED_BY_PROC_STATE: + return "ALLOWED_BY_PROC_STATE"; + case FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST: + return "ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST"; default: return ""; } } private static boolean isFgsBgStart(@FgsFeatureRetCode int code) { - return code != FGS_FEATURE_ALLOWED_BY_PROC_STATE + return code != FGS_FEATURE_ALLOWED_BY_UID_STATE && code != FGS_FEATURE_ALLOWED_BY_UID_VISIBLE; } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 01d0a6dec81a..771f273781fa 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1329,6 +1329,8 @@ public final class OomAdjuster { app.setCached(false); app.shouldNotFreeze = false; + app.mAllowStartFgsState = PROCESS_STATE_NONEXISTENT; + final int appUid = app.info.uid; final int logUid = mService.mCurOomAdjUid; @@ -1349,6 +1351,7 @@ public final class OomAdjuster { app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT); app.curCapability = PROCESS_CAPABILITY_ALL; app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT); + app.bumpAllowStartFgsState(PROCESS_STATE_PERSISTENT); // System processes can do UI, and when they do we want to have // them trim their memory after the user leaves the UI. To // facilitate this, here we need to determine whether or not it @@ -1403,6 +1406,7 @@ public final class OomAdjuster { app.adjType = "top-activity"; foregroundActivities = true; procState = PROCESS_STATE_CUR_TOP; + app.bumpAllowStartFgsState(PROCESS_STATE_TOP); if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app); } @@ -1500,6 +1504,7 @@ public final class OomAdjuster { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = PROCESS_STATE_FOREGROUND_SERVICE; + app.bumpAllowStartFgsState(PROCESS_STATE_FOREGROUND_SERVICE); app.adjType = "fg-service"; app.setCached(false); schedGroup = ProcessList.SCHED_GROUP_DEFAULT; @@ -1887,7 +1892,9 @@ public final class OomAdjuster { // into the top state, since they are not on top. Instead // give them the best bound state after that. if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) { - clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; ; + clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; + app.bumpAllowStartFgsState( + PROCESS_STATE_BOUND_FOREGROUND_SERVICE); } else if (mService.mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) @@ -1901,6 +1908,7 @@ public final class OomAdjuster { // Go at most to BOUND_TOP, unless requested to elevate // to client's state. clientProcState = PROCESS_STATE_BOUND_TOP; + app.bumpAllowStartFgsState(PROCESS_STATE_BOUND_TOP); boolean enabled = false; try { enabled = mPlatformCompatCache.isChangeEnabled( diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 5dbaaaf447ff..85c5bdc7b463 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -353,6 +353,10 @@ class ProcessRecord implements WindowProcessListener { long mKillTime; // The timestamp in uptime when this process was killed. + // If the proc state is PROCESS_STATE_BOUND_FOREGROUND_SERVICE or above, it can start FGS. + // It must obtain the proc state from a persistent/top process or FGS, not transitive. + int mAllowStartFgsState = PROCESS_STATE_NONEXISTENT; + void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo, long startTime) { this.startUid = startUid; @@ -466,6 +470,8 @@ class ProcessRecord implements WindowProcessListener { pw.print(" setCapability="); ActivityManager.printCapabilitiesFull(pw, setCapability); pw.println(); + pw.print(prefix); pw.print("allowStartFgsState="); + pw.println(mAllowStartFgsState); if (hasShownUi || mPendingUiClean || hasAboveClient || treatLikeActivity) { pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi); pw.print(" pendingUiClean="); pw.print(mPendingUiClean); @@ -1942,6 +1948,12 @@ class ProcessRecord implements WindowProcessListener { return mDialogController; } + void bumpAllowStartFgsState(int newProcState) { + if (newProcState < mAllowStartFgsState) { + mAllowStartFgsState = newProcState; + } + } + /** A controller to generate error dialogs in {@link ProcessRecord} */ class ErrorDialogController { /** dialogs being displayed due to crash */ |