Merge "Allow FGS start for proc state BOUND_FOREGROUND_SERVICE and above."

This commit is contained in:
Hui Yu
2020-11-10 17:27:21 +00:00
committed by Android (Google) Code Review
3 changed files with 107 additions and 46 deletions

View File

@@ -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;
}

View File

@@ -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(

View File

@@ -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 */