Remove the tentative FGS logic
Bug: 276963716 Test: atest CtsShortFgsTestCasesatest android.app.cts.ActivityManagerFgsBgStartTest Change-Id: Ifb322f9603aad841b4947038574d5d1a42d3dc10
This commit is contained in:
@@ -2156,7 +2156,6 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean enableFgsWhileInUseFix = mAm.mConstants.mEnableFgsWhileInUseFix;
|
||||
final boolean fgsTypeChangingFromShortFgs = r.isForeground && isOldTypeShortFgs;
|
||||
|
||||
if (fgsTypeChangingFromShortFgs) {
|
||||
@@ -2214,19 +2213,7 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
boolean resetNeededForLogging = false;
|
||||
|
||||
// Re-evaluate mAllowWhileInUsePermissionInFgs and mAllowStartForeground
|
||||
// (i.e. while-in-use and BFSL flags) if needed.
|
||||
//
|
||||
// Consider the below if-else section to be in the else of the above
|
||||
// `if (fgsTypeChangingFromShortFgs)`.
|
||||
// Using an else would increase the indent further, so we don't use it here
|
||||
// and instead just add !fgsTypeChangingFromShortFgs to all if's.
|
||||
//
|
||||
// The first if's are for the original while-in-use logic.
|
||||
if (!fgsTypeChangingFromShortFgs && !enableFgsWhileInUseFix
|
||||
&& r.mStartForegroundCount == 0) {
|
||||
if (!fgsTypeChangingFromShortFgs && r.mStartForegroundCount == 0) {
|
||||
/*
|
||||
If the service was started with startService(), not
|
||||
startForegroundService(), and if startForeground() isn't called within
|
||||
@@ -2257,8 +2244,7 @@ public final class ActiveServices {
|
||||
r.mLoggedInfoAllowStartForeground = false;
|
||||
}
|
||||
}
|
||||
} else if (!fgsTypeChangingFromShortFgs && !enableFgsWhileInUseFix
|
||||
&& r.mStartForegroundCount >= 1) {
|
||||
} else if (!fgsTypeChangingFromShortFgs && r.mStartForegroundCount >= 1) {
|
||||
// We get here if startForeground() is called multiple times
|
||||
// on the same service after it's created, regardless of whether
|
||||
// stopForeground() has been called or not.
|
||||
@@ -2269,100 +2255,6 @@ public final class ActiveServices {
|
||||
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
|
||||
BackgroundStartPrivileges.NONE,
|
||||
false /* isBindService */, false /* isStartService */);
|
||||
} else if (!fgsTypeChangingFromShortFgs && enableFgsWhileInUseFix) {
|
||||
// The new while-in-use logic.
|
||||
//
|
||||
// When startForeground() is called, we _always_ call
|
||||
// setFgsRestrictionLocked() to set the restrictions according to the
|
||||
// current state of the app.
|
||||
// (So if the app is now in TOP, for example, the service will now always
|
||||
// get while-in-use permissions.)
|
||||
//
|
||||
// Note, setFgsRestrictionLocked() will never disallow
|
||||
// mAllowWhileInUsePermissionInFgs nor mAllowStartForeground
|
||||
// (i.e. while-in-use and BFSL flags) once they're set to "allowed".
|
||||
//
|
||||
// HOWEVER, if these flags were set to "allowed" in Context.startService()
|
||||
// (as opposed to startForegroundService()), when the service wasn't yet
|
||||
// a foreground service, then we may not always
|
||||
// want to trust them -- for example, if the service has been running as a
|
||||
// BG service or a bound service for a long time when the app is not longer
|
||||
// in the foreground, then we shouldn't grant while-in-user nor BFSL.
|
||||
// So in that case, we need to reset it first.
|
||||
|
||||
final long delayMs =
|
||||
(r.mLastUntrustedSetFgsRestrictionAllowedTime == 0) ? 0
|
||||
: (SystemClock.elapsedRealtime()
|
||||
- r.mLastUntrustedSetFgsRestrictionAllowedTime);
|
||||
final boolean resetNeeded =
|
||||
!r.isForeground
|
||||
&& delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs;
|
||||
if (resetNeeded) {
|
||||
// We don't want to reset mDebugWhileInUseReasonInBindService here --
|
||||
// we'll instead reset it in the following code, using the simulated
|
||||
// legacy logic.
|
||||
resetFgsRestrictionLocked(r,
|
||||
/*resetDebugWhileInUseReasonInBindService=*/ false);
|
||||
}
|
||||
|
||||
// Simulate the reset flow in the legacy logic to reset
|
||||
// mDebugWhileInUseReasonInBindService.
|
||||
// (Which is only used to compare to the old logic.)
|
||||
final long legacyDelayMs = SystemClock.elapsedRealtime() - r.createRealTime;
|
||||
if ((r.mStartForegroundCount == 0)
|
||||
&& (legacyDelayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs)) {
|
||||
r.mDebugWhileInUseReasonInBindService = REASON_DENIED;
|
||||
}
|
||||
|
||||
setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
|
||||
r.appInfo.uid, r.intent.getIntent(), r, r.userId,
|
||||
BackgroundStartPrivileges.NONE,
|
||||
false /* isBindService */, false /* isStartService */);
|
||||
|
||||
final String temp = "startForegroundDelayMs:" + delayMs
|
||||
+ "; started: " + r.startRequested
|
||||
+ "; num_bindings: " + r.getConnections().size()
|
||||
+ "; wasForeground: " + r.isForeground
|
||||
+ "; resetNeeded:" + resetNeeded;
|
||||
if (r.mInfoAllowStartForeground != null) {
|
||||
r.mInfoAllowStartForeground += "; " + temp;
|
||||
} else {
|
||||
r.mInfoAllowStartForeground = temp;
|
||||
}
|
||||
r.mLoggedInfoAllowStartForeground = false;
|
||||
|
||||
resetNeededForLogging = resetNeeded;
|
||||
}
|
||||
|
||||
// If the service has any bindings and it's not yet a FGS
|
||||
// we compare the new and old while-in-use logics.
|
||||
// (If it's not the first startForeground() call, we already reset the
|
||||
// while-in-use and BFSL flags, so the logic change wouldn't matter.)
|
||||
//
|
||||
// Note, mDebugWhileInUseReasonInBindService does *not* fully simulate the
|
||||
// legacy logic, because we'll only set it in bindService(), but the actual
|
||||
// mAllowWhileInUsePermissionInFgsReason can change afterwards, in a subsequent
|
||||
// Service.startForeground(). This check will only provide "rough" check.
|
||||
// But if mDebugWhileInUseReasonInBindService is _not_ DENIED, and
|
||||
// mDebugWhileInUseReasonInStartForeground _is_ DENIED, then that means we'd
|
||||
// now detected a behavior change.
|
||||
// OTOH, if it's changing from non-DENIED to another non-DENIED, that may
|
||||
// not be a problem.
|
||||
if (enableFgsWhileInUseFix
|
||||
&& !r.isForeground
|
||||
&& (r.getConnections().size() > 0)
|
||||
&& (r.mDebugWhileInUseReasonInBindService
|
||||
!= r.mDebugWhileInUseReasonInStartForeground)) {
|
||||
logWhileInUseChangeWtf("FGS while-in-use changed (b/276963716): old="
|
||||
+ reasonCodeToString(r.mDebugWhileInUseReasonInBindService)
|
||||
+ " new="
|
||||
+ reasonCodeToString(r.mDebugWhileInUseReasonInStartForeground)
|
||||
+ " startForegroundCount=" + r.mStartForegroundCount
|
||||
+ " started=" + r.startRequested
|
||||
+ " num_bindings=" + r.getConnections().size()
|
||||
+ " resetNeeded=" + resetNeededForLogging
|
||||
+ " "
|
||||
+ r.shortInstanceName);
|
||||
}
|
||||
|
||||
// If the foreground service is not started from TOP process, do not allow it to
|
||||
@@ -2471,10 +2363,6 @@ public final class ActiveServices {
|
||||
}
|
||||
r.isForeground = true;
|
||||
|
||||
// Once the service becomes a foreground service,
|
||||
// the FGS restriction information always becomes "trustable".
|
||||
r.mLastUntrustedSetFgsRestrictionAllowedTime = 0;
|
||||
|
||||
// The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could
|
||||
// be deferred, make a copy of mAllowStartForeground and
|
||||
// mAllowWhileInUsePermissionInFgs.
|
||||
@@ -2620,13 +2508,6 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It just does a wtf, but extracted to a method, so we can do a signature search on pitot.
|
||||
*/
|
||||
private void logWhileInUseChangeWtf(String message) {
|
||||
Slog.wtf(TAG, message);
|
||||
}
|
||||
|
||||
private boolean withinFgsDeferRateLimit(ServiceRecord sr, final long now) {
|
||||
// If we're still within the service's deferral period, then by definition
|
||||
// deferral is not rate limited.
|
||||
@@ -3839,25 +3720,9 @@ public final class ActiveServices {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!mAm.mConstants.mEnableFgsWhileInUseFix) {
|
||||
// Old while-in-use logic.
|
||||
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId,
|
||||
BackgroundStartPrivileges.NONE, true /* isBindService */,
|
||||
false /* isStartService */);
|
||||
} else {
|
||||
// New logic will not call setFgsRestrictionLocked() here, but we still
|
||||
// keep track of the allow reason from the old logic here, so we can compare to
|
||||
// the new logic.
|
||||
// Once we're confident enough in the new logic, we should remove it.
|
||||
if (s.mDebugWhileInUseReasonInBindService == REASON_DENIED) {
|
||||
s.mDebugWhileInUseReasonInBindService =
|
||||
shouldAllowFgsWhileInUsePermissionLocked(
|
||||
callingPackage, callingPid, callingUid, s.app,
|
||||
BackgroundStartPrivileges.NONE,
|
||||
true /* isBindService */,
|
||||
false /* DO NOT enableFgsWhileInUseFix; use the old logic */);
|
||||
}
|
||||
}
|
||||
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId,
|
||||
BackgroundStartPrivileges.NONE, true /* isBindService */,
|
||||
false /* isStartService */);
|
||||
|
||||
if (s.app != null) {
|
||||
ProcessServiceRecord servicePsr = s.app.mServices;
|
||||
@@ -7554,15 +7419,13 @@ public final class ActiveServices {
|
||||
* @param r the service to start.
|
||||
* @param isStartService True if it's called from Context.startService().
|
||||
* False if it's called from Context.startForegroundService() or
|
||||
* Service.startService().
|
||||
* Service.startForeground().
|
||||
* @return true if allow, false otherwise.
|
||||
*/
|
||||
private void setFgsRestrictionLocked(String callingPackage,
|
||||
int callingPid, int callingUid, Intent intent, ServiceRecord r, int userId,
|
||||
BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService,
|
||||
boolean isStartService) {
|
||||
final long now = SystemClock.elapsedRealtime();
|
||||
|
||||
// Check DeviceConfig flag.
|
||||
if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
|
||||
r.mAllowWhileInUsePermissionInFgs = true;
|
||||
@@ -7580,60 +7443,30 @@ public final class ActiveServices {
|
||||
isBindService);
|
||||
// We store them to compare the old and new while-in-use logics to each other.
|
||||
// (They're not used for any other purposes.)
|
||||
if (isBindService) {
|
||||
r.mDebugWhileInUseReasonInBindService = allowWhileInUse;
|
||||
} else {
|
||||
r.mDebugWhileInUseReasonInStartForeground = allowWhileInUse;
|
||||
}
|
||||
if (!r.mAllowWhileInUsePermissionInFgs) {
|
||||
r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED);
|
||||
newlyAllowed |= r.mAllowWhileInUsePermissionInFgs;
|
||||
}
|
||||
if (r.mAllowStartForeground == REASON_DENIED) {
|
||||
r.mAllowStartForeground = shouldAllowFgsStartForegroundWithBindingCheckLocked(
|
||||
allowWhileInUse, callingPackage, callingPid, callingUid, intent, r,
|
||||
backgroundStartPrivileges, isBindService);
|
||||
newlyAllowed |= r.mAllowStartForeground != REASON_DENIED;
|
||||
}
|
||||
} else {
|
||||
allowWhileInUse = REASON_UNKNOWN;
|
||||
}
|
||||
r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse;
|
||||
|
||||
if (isStartService && !r.isForeground && newlyAllowed) {
|
||||
// If it's called by Context.startService() (not by startForegroundService()),
|
||||
// and we're setting "allowed", then we can't fully trust it yet -- we'll need to reset
|
||||
// the restrictions if startForeground() is called after the grace period.
|
||||
r.mLastUntrustedSetFgsRestrictionAllowedTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset various while-in-use and BFSL related information.
|
||||
*/
|
||||
void resetFgsRestrictionLocked(ServiceRecord r) {
|
||||
resetFgsRestrictionLocked(r, /*resetDebugWhileInUseReasonInBindService=*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset various while-in-use and BFSL related information.
|
||||
*/
|
||||
void resetFgsRestrictionLocked(ServiceRecord r,
|
||||
boolean resetDebugWhileInUseReasonInBindService) {
|
||||
r.mAllowWhileInUsePermissionInFgs = false;
|
||||
r.mAllowWhileInUsePermissionInFgsReason = REASON_DENIED;
|
||||
r.mDebugWhileInUseReasonInStartForeground = REASON_DENIED;
|
||||
|
||||
// In Service.startForeground(), we reset this field using a legacy logic,
|
||||
// so resetting this field is optional.
|
||||
if (resetDebugWhileInUseReasonInBindService) {
|
||||
r.mDebugWhileInUseReasonInBindService = REASON_DENIED;
|
||||
}
|
||||
r.mAllowStartForeground = REASON_DENIED;
|
||||
r.mInfoAllowStartForeground = null;
|
||||
r.mInfoTempFgsAllowListReason = null;
|
||||
r.mLoggedInfoAllowStartForeground = false;
|
||||
r.mLastUntrustedSetFgsRestrictionAllowedTime = 0;
|
||||
r.updateAllowUiJobScheduling(r.mAllowWhileInUsePermissionInFgs);
|
||||
}
|
||||
|
||||
@@ -7668,22 +7501,11 @@ public final class ActiveServices {
|
||||
private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
|
||||
int callingPid, int callingUid, @Nullable ProcessRecord targetProcess,
|
||||
BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) {
|
||||
return shouldAllowFgsWhileInUsePermissionLocked(callingPackage,
|
||||
callingPid, callingUid, targetProcess, backgroundStartPrivileges, isBindService,
|
||||
/* enableFgsWhileInUseFix =*/ mAm.mConstants.mEnableFgsWhileInUseFix);
|
||||
}
|
||||
|
||||
private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage,
|
||||
int callingPid, int callingUid, @Nullable ProcessRecord targetProcess,
|
||||
BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService,
|
||||
boolean enableFgsWhileInUseFix) {
|
||||
int ret = REASON_DENIED;
|
||||
|
||||
// Define some local variables for better readability...
|
||||
final boolean useOldLogic = !enableFgsWhileInUseFix;
|
||||
final boolean forStartForeground = !isBindService;
|
||||
|
||||
if (useOldLogic || forStartForeground) {
|
||||
if (forStartForeground) {
|
||||
final int uidState = mAm.getUidStateLocked(callingUid);
|
||||
if (ret == REASON_DENIED) {
|
||||
// Allow FGS while-in-use if the caller's process state is PROCESS_STATE_PERSISTENT,
|
||||
@@ -7733,10 +7555,6 @@ public final class ActiveServices {
|
||||
}
|
||||
}
|
||||
|
||||
if (enableFgsWhileInUseFix && ret == REASON_DENIED) {
|
||||
ret = shouldAllowFgsWhileInUsePermissionByBindingsLocked(callingUid);
|
||||
}
|
||||
|
||||
if (ret == REASON_DENIED) {
|
||||
// Allow FGS while-in-use if the WindowManager allows background activity start.
|
||||
// This is mainly to get the 10 seconds grace period if any activity in the caller has
|
||||
|
||||
@@ -1058,13 +1058,6 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
/** @see #KEY_USE_MODERN_TRIM */
|
||||
public boolean USE_MODERN_TRIM = DEFAULT_USE_MODERN_TRIM;
|
||||
|
||||
private static final String KEY_ENABLE_FGS_WHILE_IN_USE_FIX =
|
||||
"key_enable_fgs_while_in_use_fix";
|
||||
|
||||
private static final boolean DEFAULT_ENABLE_FGS_WHILE_IN_USE_FIX = false;
|
||||
|
||||
public volatile boolean mEnableFgsWhileInUseFix = DEFAULT_ENABLE_FGS_WHILE_IN_USE_FIX;
|
||||
|
||||
private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
|
||||
new OnPropertiesChangedListener() {
|
||||
@Override
|
||||
@@ -1233,9 +1226,6 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
|
||||
updateEnableWaitForFinishAttachApplication();
|
||||
break;
|
||||
case KEY_ENABLE_FGS_WHILE_IN_USE_FIX:
|
||||
updateEnableFgsWhileInUseFix();
|
||||
break;
|
||||
case KEY_MAX_PREVIOUS_TIME:
|
||||
updateMaxPreviousTime();
|
||||
break;
|
||||
@@ -2005,12 +1995,6 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
|
||||
}
|
||||
|
||||
private void updateEnableFgsWhileInUseFix() {
|
||||
mEnableFgsWhileInUseFix = DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_ENABLE_FGS_WHILE_IN_USE_FIX,
|
||||
DEFAULT_ENABLE_FGS_WHILE_IN_USE_FIX);
|
||||
}
|
||||
private void updateUseTieredCachedAdj() {
|
||||
USE_TIERED_CACHED_ADJ = DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -2211,9 +2195,6 @@ final class ActivityManagerConstants extends ContentObserver {
|
||||
pw.print(" "); pw.print(KEY_SYSTEM_EXEMPT_POWER_RESTRICTIONS_ENABLED);
|
||||
pw.print("="); pw.println(mFlagSystemExemptPowerRestrictionsEnabled);
|
||||
|
||||
pw.print(" "); pw.print(KEY_ENABLE_FGS_WHILE_IN_USE_FIX);
|
||||
pw.print("="); pw.println(mEnableFgsWhileInUseFix);
|
||||
|
||||
pw.print(" "); pw.print(KEY_SHORT_FGS_TIMEOUT_DURATION);
|
||||
pw.print("="); pw.println(mShortFgsTimeoutDuration);
|
||||
pw.print(" "); pw.print(KEY_SHORT_FGS_PROC_STATE_EXTRA_WAIT_DURATION);
|
||||
|
||||
@@ -177,12 +177,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
@PowerExemptionManager.ReasonCode
|
||||
int mAllowWhileInUsePermissionInFgsReason = REASON_DENIED;
|
||||
|
||||
// Integer version of mAllowWhileInUsePermissionInFgs that we keep track to compare
|
||||
// the old and new logics.
|
||||
// TODO: Remove them once we're confident in the new logic.
|
||||
int mDebugWhileInUseReasonInStartForeground = REASON_DENIED;
|
||||
int mDebugWhileInUseReasonInBindService = REASON_DENIED;
|
||||
|
||||
// A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state.
|
||||
boolean mAllowWhileInUsePermissionInFgsAtEntering;
|
||||
/** Allow scheduling user-initiated jobs from the background. */
|
||||
@@ -224,13 +218,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
// is called.
|
||||
int mStartForegroundCount;
|
||||
|
||||
// Last time mAllowWhileInUsePermissionInFgs or mAllowStartForeground was set to "allowed"
|
||||
// from "disallowed" when the service was _not_ already a foreground service.
|
||||
// this means they're set in startService(). (not startForegroundService)
|
||||
// In startForeground(), if this timestamp is too old, we can't trust these flags, so
|
||||
// we need to reset them.
|
||||
long mLastUntrustedSetFgsRestrictionAllowedTime;
|
||||
|
||||
// This is a service record of a FGS delegate (not a service record of a real service)
|
||||
boolean mIsFgsDelegate;
|
||||
@Nullable ForegroundServiceDelegation mFgsDelegation;
|
||||
@@ -624,12 +611,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
pw.print(prefix); pw.print("mAllowWhileInUsePermissionInFgsReason=");
|
||||
pw.println(PowerExemptionManager.reasonCodeToString(mAllowWhileInUsePermissionInFgsReason));
|
||||
|
||||
pw.print(prefix); pw.print("debugWhileInUseReasonInStartForeground=");
|
||||
pw.println(PowerExemptionManager.reasonCodeToString(
|
||||
mDebugWhileInUseReasonInStartForeground));
|
||||
pw.print(prefix); pw.print("debugWhileInUseReasonInBindService=");
|
||||
pw.println(PowerExemptionManager.reasonCodeToString(mDebugWhileInUseReasonInBindService));
|
||||
|
||||
pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling);
|
||||
pw.print(prefix); pw.print("recentCallingPackage=");
|
||||
pw.println(mRecentCallingPackage);
|
||||
@@ -642,10 +623,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
|
||||
pw.print(prefix); pw.print("infoAllowStartForeground=");
|
||||
pw.println(mInfoAllowStartForeground);
|
||||
|
||||
pw.print(prefix); pw.print("lastUntrustedSetFgsRestrictionAllowedTime=");
|
||||
TimeUtils.formatDuration(mLastUntrustedSetFgsRestrictionAllowedTime, now, pw);
|
||||
pw.println();
|
||||
|
||||
if (delayed) {
|
||||
pw.print(prefix); pw.print("delayed="); pw.println(delayed);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user