Loading services/core/java/com/android/server/am/ActiveServices.java +68 −44 Original line number Diff line number Diff line Loading @@ -256,7 +256,7 @@ import java.util.function.Predicate; public final class ActiveServices { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM; private static final String TAG_MU = TAG + POSTFIX_MU; private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE; static final String TAG_SERVICE = TAG + POSTFIX_SERVICE; private static final String TAG_SERVICE_EXECUTING = TAG + POSTFIX_SERVICE_EXECUTING; private static final boolean DEBUG_DELAYED_SERVICE = DEBUG_SERVICE; Loading Loading @@ -850,8 +850,7 @@ public final class ActiveServices { // Service.startForeground()), at that point we will consult the BFSL check and the timeout // and make the necessary decisions. setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId, backgroundStartPrivileges, false /* isBindService */, !fgRequired /* isStartService */); backgroundStartPrivileges, false /* isBindService */); if (!mAm.mUserController.exists(r.userId)) { Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId); Loading Loading @@ -894,7 +893,7 @@ public final class ActiveServices { if (fgRequired) { logFgsBackgroundStart(r); if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) { if (!r.isFgsAllowedStart() && isBgFgsRestrictionEnabled(r)) { String msg = "startForegroundService() not allowed due to " + "mAllowStartForeground false: service " + r.shortInstanceName; Loading Loading @@ -1060,7 +1059,7 @@ public final class ActiveServices { // Use that as a shortcut if possible to avoid having to recheck all the conditions. final boolean whileInUseAllowsUiJobScheduling = ActivityManagerService.doesReasonCodeAllowSchedulingUserInitiatedJobs( r.mAllowWhileInUsePermissionInFgsReason); r.getFgsAllowWIU()); r.updateAllowUiJobScheduling(whileInUseAllowsUiJobScheduling || mAm.canScheduleUserInitiatedJobs(callingUid, callingPid, callingPackage)); } else { Loading Loading @@ -2178,12 +2177,12 @@ public final class ActiveServices { // on a SHORT_SERVICE FGS. // See if the app could start an FGS or not. r.mAllowStartForeground = REASON_DENIED; r.clearFgsAllowStart(); setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); if (r.mAllowStartForeground == REASON_DENIED) { false /* isBindService */); if (!r.isFgsAllowedStart()) { Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: " + " BFSL DENIED."); } else { Loading @@ -2191,13 +2190,13 @@ public final class ActiveServices { Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: " + " BFSL Allowed: " + PowerExemptionManager.reasonCodeToString( r.mAllowStartForeground)); r.getFgsAllowStart())); } } final boolean fgsStartAllowed = !isBgFgsRestrictionEnabledForService || (r.mAllowStartForeground != REASON_DENIED); || r.isFgsAllowedStart(); if (fgsStartAllowed) { if (isNewTypeShortFgs) { Loading Loading @@ -2246,7 +2245,7 @@ public final class ActiveServices { setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); false /* isBindService */); final String temp = "startForegroundDelayMs:" + delayMs; if (r.mInfoAllowStartForeground != null) { r.mInfoAllowStartForeground += "; " + temp; Loading @@ -2266,20 +2265,21 @@ public final class ActiveServices { setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); false /* isBindService */); } // If the foreground service is not started from TOP process, do not allow it to // have while-in-use location/camera/microphone access. if (!r.mAllowWhileInUsePermissionInFgs) { if (!r.isFgsAllowedWIU()) { Slog.w(TAG, "Foreground service started from background can not have " + "location/camera/microphone access: service " + r.shortInstanceName); } r.maybeLogFgsLogicChange(); if (!bypassBfslCheck) { logFgsBackgroundStart(r); if (r.mAllowStartForeground == REASON_DENIED if (!r.isFgsAllowedStart() && isBgFgsRestrictionEnabledForService) { final String msg = "Service.startForeground() not allowed due to " + "mAllowStartForeground false: service " Loading Loading @@ -2378,9 +2378,9 @@ public final class ActiveServices { // The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could // be deferred, make a copy of mAllowStartForeground and // mAllowWhileInUsePermissionInFgs. r.mAllowStartForegroundAtEntering = r.mAllowStartForeground; r.mAllowStartForegroundAtEntering = r.getFgsAllowStart(); r.mAllowWhileInUsePermissionInFgsAtEntering = r.mAllowWhileInUsePermissionInFgs; r.isFgsAllowedWIU(); r.mStartForegroundCount++; r.mFgsEnterTime = SystemClock.uptimeMillis(); if (!stopProcStatsOp) { Loading Loading @@ -2558,7 +2558,7 @@ public final class ActiveServices { policy.getForegroundServiceTypePolicyInfo(type, defaultToType); final @ForegroundServicePolicyCheckCode int code = policy.checkForegroundServiceTypePolicy( mAm.mContext, r.packageName, r.app.uid, r.app.getPid(), r.mAllowWhileInUsePermissionInFgs, policyInfo); r.isFgsAllowedWIU(), policyInfo); RuntimeException exception = null; switch (code) { case FGS_TYPE_POLICY_CHECK_DEPRECATED: { Loading Loading @@ -3744,8 +3744,7 @@ public final class ActiveServices { } } setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId, BackgroundStartPrivileges.NONE, true /* isBindService */, false /* isStartService */); BackgroundStartPrivileges.NONE, true /* isBindService */); if (s.app != null) { ProcessServiceRecord servicePsr = s.app.mServices; Loading Loading @@ -7443,54 +7442,80 @@ public final class ActiveServices { * @param callingUid caller app's uid. * @param intent intent to start/bind service. * @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.startForeground(). * @param isBindService True if it's called from bindService(). * @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) { BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) { @ReasonCode int allowWIU; @ReasonCode int allowStart; // If called from bindService(), do not update the actual fields, but instead // keep it in a separate set of fields. if (isBindService) { allowWIU = r.mAllowWIUInBindService; allowStart = r.mAllowStartInBindService; } else { allowWIU = r.mAllowWhileInUsePermissionInFgsReasonNoBinding; allowStart = r.mAllowStartForegroundNoBinding; } // Check DeviceConfig flag. if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) { if (!r.mAllowWhileInUsePermissionInFgs) { if (allowWIU == REASON_DENIED) { // BGFGS start restrictions are disabled. We're allowing while-in-use permissions. // Note REASON_OTHER since there's no other suitable reason. r.mAllowWhileInUsePermissionInFgsReason = REASON_OTHER; allowWIU = REASON_OTHER; } r.mAllowWhileInUsePermissionInFgs = true; } if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == REASON_DENIED)) { if ((allowWIU == REASON_DENIED) || (allowStart == REASON_DENIED)) { @ReasonCode final int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges); // 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 (!r.mAllowWhileInUsePermissionInFgs) { r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED); r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse; if (allowWIU == REASON_DENIED) { allowWIU = allowWhileInUse; } if (r.mAllowStartForeground == REASON_DENIED) { r.mAllowStartForeground = shouldAllowFgsStartForegroundWithBindingCheckLocked( if (allowStart == REASON_DENIED) { allowStart = shouldAllowFgsStartForegroundWithBindingCheckLocked( allowWhileInUse, callingPackage, callingPid, callingUid, intent, r, backgroundStartPrivileges, isBindService); } } if (isBindService) { r.mAllowWIUInBindService = allowWIU; r.mAllowStartInBindService = allowStart; } else { r.mAllowWhileInUsePermissionInFgsReasonNoBinding = allowWIU; r.mAllowStartForegroundNoBinding = allowStart; // Also do a binding client check, unless called from bindService(). if (r.mAllowWIUByBindings == REASON_DENIED) { r.mAllowWIUByBindings = shouldAllowFgsWhileInUsePermissionByBindingsLocked(callingUid); } if (r.mAllowStartByBindings == REASON_DENIED) { r.mAllowStartByBindings = r.mAllowWIUByBindings; } } } /** * Reset various while-in-use and BFSL related information. */ void resetFgsRestrictionLocked(ServiceRecord r) { r.mAllowWhileInUsePermissionInFgs = false; r.mAllowWhileInUsePermissionInFgsReason = REASON_DENIED; r.mAllowStartForeground = REASON_DENIED; r.clearFgsAllowWIU(); r.clearFgsAllowStart(); r.mInfoAllowStartForeground = null; r.mInfoTempFgsAllowListReason = null; r.mLoggedInfoAllowStartForeground = false; r.updateAllowUiJobScheduling(r.mAllowWhileInUsePermissionInFgs); r.updateAllowUiJobScheduling(r.isFgsAllowedWIU()); } boolean canStartForegroundServiceLocked(int callingPid, int callingUid, String callingPackage) { Loading Loading @@ -8062,10 +8087,10 @@ public final class ActiveServices { */ if (!r.mLoggedInfoAllowStartForeground) { final String msg = "Background started FGS: " + ((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ") + (r.isFgsAllowedStart() ? "Allowed " : "Disallowed ") + r.mInfoAllowStartForeground + (r.isShortFgs() ? " (Called on SHORT_SERVICE)" : ""); if (r.mAllowStartForeground != REASON_DENIED) { if (r.isFgsAllowedStart()) { if (ActivityManagerUtils.shouldSamplePackageForAtom(r.packageName, mAm.mConstants.mFgsStartAllowedLogSampleRate)) { Slog.wtfQuiet(TAG, msg); Loading Loading @@ -8105,8 +8130,8 @@ public final class ActiveServices { allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering; fgsStartReasonCode = r.mAllowStartForegroundAtEntering; } else { allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgs; fgsStartReasonCode = r.mAllowStartForeground; allowWhileInUsePermissionInFgs = r.isFgsAllowedWIU(); fgsStartReasonCode = r.getFgsAllowStart(); } final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0; Loading Loading @@ -8295,8 +8320,7 @@ public final class ActiveServices { r.mFgsEnterTime = SystemClock.uptimeMillis(); r.foregroundServiceType = options.mForegroundServiceTypes; setFgsRestrictionLocked(callingPackage, callingPid, callingUid, intent, r, userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); BackgroundStartPrivileges.NONE, false /* isBindService */); final ProcessServiceRecord psr = callerApp.mServices; final boolean newService = psr.startService(r); // updateOomAdj. Loading services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java +2 −2 Original line number Diff line number Diff line Loading @@ -479,8 +479,8 @@ public class ForegroundServiceTypeLoggerModule { r.appInfo.uid, r.shortInstanceName, fgsState, // FGS State r.mAllowWhileInUsePermissionInFgs, // allowWhileInUsePermissionInFgs r.mAllowStartForeground, // fgsStartReasonCode r.isFgsAllowedWIU(), // allowWhileInUsePermissionInFgs r.getFgsAllowStart(), // fgsStartReasonCode r.appInfo.targetSdkVersion, r.mRecentCallingUid, 0, // callerTargetSdkVersion Loading services/core/java/com/android/server/am/OomAdjuster.java +1 −1 Original line number Diff line number Diff line Loading @@ -2222,7 +2222,7 @@ public class OomAdjuster { if (s.isForeground) { final int fgsType = s.foregroundServiceType; if (s.mAllowWhileInUsePermissionInFgs) { if (s.isFgsAllowedWIU()) { capabilityFromFGS |= (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; Loading services/core/java/com/android/server/am/ServiceRecord.java +120 −8 Original line number Diff line number Diff line Loading @@ -21,9 +21,11 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE; import static android.os.PowerExemptionManager.REASON_DENIED; import static android.os.PowerExemptionManager.reasonCodeToString; import static android.os.Process.INVALID_UID; import static com.android.internal.util.Preconditions.checkArgument; import static com.android.server.am.ActiveServices.TAG_SERVICE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; Loading Loading @@ -172,11 +174,11 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN private BackgroundStartPrivileges mBackgroundStartPrivilegesByStartMerged = BackgroundStartPrivileges.NONE; // allow while-in-use permissions in foreground service or not. // Reason code for allow while-in-use permissions in foreground service. // If it's not DENIED, while-in-use permissions are allowed. // while-in-use permissions in FGS started from background might be restricted. boolean mAllowWhileInUsePermissionInFgs; @PowerExemptionManager.ReasonCode int mAllowWhileInUsePermissionInFgsReason = REASON_DENIED; int mAllowWhileInUsePermissionInFgsReasonNoBinding = REASON_DENIED; // A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state. boolean mAllowWhileInUsePermissionInFgsAtEntering; Loading Loading @@ -205,15 +207,114 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // allow the service becomes foreground service? Service started from background may not be // allowed to become a foreground service. @PowerExemptionManager.ReasonCode int mAllowStartForeground = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartForegroundNoBinding = REASON_DENIED; // A copy of mAllowStartForeground's value when the service is entering FGS state. @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED; // Debug info why mAllowStartForeground is allowed or denied. String mInfoAllowStartForeground; // Debug info if mAllowStartForeground is allowed because of a temp-allowlist. ActivityManagerService.FgsTempAllowListItem mInfoTempFgsAllowListReason; // Is the same mInfoAllowStartForeground string has been logged before? Used for dedup. boolean mLoggedInfoAllowStartForeground; @PowerExemptionManager.ReasonCode int mAllowWIUInBindService = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowWIUByBindings = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartInBindService = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartByBindings = REASON_DENIED; @PowerExemptionManager.ReasonCode int getFgsAllowWIU() { return mAllowWhileInUsePermissionInFgsReasonNoBinding != REASON_DENIED ? mAllowWhileInUsePermissionInFgsReasonNoBinding : mAllowWIUInBindService; } boolean isFgsAllowedWIU() { return getFgsAllowWIU() != REASON_DENIED; } @PowerExemptionManager.ReasonCode int getFgsAllowStart() { return mAllowStartForegroundNoBinding != REASON_DENIED ? mAllowStartForegroundNoBinding : mAllowStartInBindService; } boolean isFgsAllowedStart() { return getFgsAllowStart() != REASON_DENIED; } void clearFgsAllowWIU() { mAllowWhileInUsePermissionInFgsReasonNoBinding = REASON_DENIED; mAllowWIUInBindService = REASON_DENIED; mAllowWIUByBindings = REASON_DENIED; } void clearFgsAllowStart() { mAllowStartForegroundNoBinding = REASON_DENIED; mAllowStartInBindService = REASON_DENIED; mAllowStartByBindings = REASON_DENIED; } @PowerExemptionManager.ReasonCode int reasonOr(@PowerExemptionManager.ReasonCode int first, @PowerExemptionManager.ReasonCode int second) { return first != REASON_DENIED ? first : second; } boolean allowedChanged(@PowerExemptionManager.ReasonCode int first, @PowerExemptionManager.ReasonCode int second) { return (first == REASON_DENIED) != (second == REASON_DENIED); } String changeMessage(@PowerExemptionManager.ReasonCode int first, @PowerExemptionManager.ReasonCode int second) { return reasonOr(first, second) == REASON_DENIED ? "DENIED" : ("ALLOWED (" + reasonCodeToString(first) + "+" + reasonCodeToString(second) + ")"); } void maybeLogFgsLogicChange() { final int origWiu = reasonOr(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUInBindService); final int newWiu = reasonOr(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUByBindings); final int origStart = reasonOr(mAllowStartForegroundNoBinding, mAllowStartInBindService); final int newStart = reasonOr(mAllowStartForegroundNoBinding, mAllowStartByBindings); final boolean wiuChanged = allowedChanged(origWiu, newWiu); final boolean startChanged = allowedChanged(origStart, newStart); if (!wiuChanged && !startChanged) { return; } final String message = "FGS logic changed:" + (wiuChanged ? " [WIU changed]" : "") + (startChanged ? " [BFSL changed]" : "") + " OW:" // Orig-WIU + changeMessage(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUInBindService) + " NW:" // New-WIU + changeMessage(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUByBindings) + " OS:" // Orig-start + changeMessage(mAllowStartForegroundNoBinding, mAllowStartInBindService) + " NS:" // New-start + changeMessage(mAllowStartForegroundNoBinding, mAllowStartByBindings); Slog.wtf(TAG_SERVICE, message); } // The number of times Service.startForeground() is called, after this service record is // created. (i.e. due to "bound" or "start".) It never decreases, even when stopForeground() // is called. Loading Loading @@ -502,7 +603,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN ProtoUtils.toDuration(proto, ServiceRecordProto.RESTART_TIME, restartTime, now); proto.write(ServiceRecordProto.CREATED_FROM_FG, createdFromFg); proto.write(ServiceRecordProto.ALLOW_WHILE_IN_USE_PERMISSION_IN_FGS, mAllowWhileInUsePermissionInFgs); isFgsAllowedWIU()); if (startRequested || delayedStop || lastStartId != 0) { long startToken = proto.start(ServiceRecordProto.START); Loading Loading @@ -618,7 +719,13 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN pw.println(mBackgroundStartPrivilegesByStartMerged); } pw.print(prefix); pw.print("mAllowWhileInUsePermissionInFgsReason="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowWhileInUsePermissionInFgsReason)); pw.println(PowerExemptionManager.reasonCodeToString( mAllowWhileInUsePermissionInFgsReasonNoBinding)); pw.print(prefix); pw.print("mAllowWIUInBindService="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowWIUInBindService)); pw.print(prefix); pw.print("mAllowWIUByBindings="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowWIUByBindings)); pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling); pw.print(prefix); pw.print("recentCallingPackage="); Loading @@ -626,7 +733,12 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN pw.print(prefix); pw.print("recentCallingUid="); pw.println(mRecentCallingUid); pw.print(prefix); pw.print("allowStartForeground="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartForeground)); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartForegroundNoBinding)); pw.print(prefix); pw.print("mAllowStartInBindService="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartInBindService)); pw.print(prefix); pw.print("mAllowStartByBindings="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartByBindings)); pw.print(prefix); pw.print("startForegroundCount="); pw.println(mStartForegroundCount); pw.print(prefix); pw.print("infoAllowStartForeground="); Loading Loading
services/core/java/com/android/server/am/ActiveServices.java +68 −44 Original line number Diff line number Diff line Loading @@ -256,7 +256,7 @@ import java.util.function.Predicate; public final class ActiveServices { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM; private static final String TAG_MU = TAG + POSTFIX_MU; private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE; static final String TAG_SERVICE = TAG + POSTFIX_SERVICE; private static final String TAG_SERVICE_EXECUTING = TAG + POSTFIX_SERVICE_EXECUTING; private static final boolean DEBUG_DELAYED_SERVICE = DEBUG_SERVICE; Loading Loading @@ -850,8 +850,7 @@ public final class ActiveServices { // Service.startForeground()), at that point we will consult the BFSL check and the timeout // and make the necessary decisions. setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId, backgroundStartPrivileges, false /* isBindService */, !fgRequired /* isStartService */); backgroundStartPrivileges, false /* isBindService */); if (!mAm.mUserController.exists(r.userId)) { Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId); Loading Loading @@ -894,7 +893,7 @@ public final class ActiveServices { if (fgRequired) { logFgsBackgroundStart(r); if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) { if (!r.isFgsAllowedStart() && isBgFgsRestrictionEnabled(r)) { String msg = "startForegroundService() not allowed due to " + "mAllowStartForeground false: service " + r.shortInstanceName; Loading Loading @@ -1060,7 +1059,7 @@ public final class ActiveServices { // Use that as a shortcut if possible to avoid having to recheck all the conditions. final boolean whileInUseAllowsUiJobScheduling = ActivityManagerService.doesReasonCodeAllowSchedulingUserInitiatedJobs( r.mAllowWhileInUsePermissionInFgsReason); r.getFgsAllowWIU()); r.updateAllowUiJobScheduling(whileInUseAllowsUiJobScheduling || mAm.canScheduleUserInitiatedJobs(callingUid, callingPid, callingPackage)); } else { Loading Loading @@ -2178,12 +2177,12 @@ public final class ActiveServices { // on a SHORT_SERVICE FGS. // See if the app could start an FGS or not. r.mAllowStartForeground = REASON_DENIED; r.clearFgsAllowStart(); setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); if (r.mAllowStartForeground == REASON_DENIED) { false /* isBindService */); if (!r.isFgsAllowedStart()) { Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: " + " BFSL DENIED."); } else { Loading @@ -2191,13 +2190,13 @@ public final class ActiveServices { Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: " + " BFSL Allowed: " + PowerExemptionManager.reasonCodeToString( r.mAllowStartForeground)); r.getFgsAllowStart())); } } final boolean fgsStartAllowed = !isBgFgsRestrictionEnabledForService || (r.mAllowStartForeground != REASON_DENIED); || r.isFgsAllowedStart(); if (fgsStartAllowed) { if (isNewTypeShortFgs) { Loading Loading @@ -2246,7 +2245,7 @@ public final class ActiveServices { setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); false /* isBindService */); final String temp = "startForegroundDelayMs:" + delayMs; if (r.mInfoAllowStartForeground != null) { r.mInfoAllowStartForeground += "; " + temp; Loading @@ -2266,20 +2265,21 @@ public final class ActiveServices { setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(), r.appInfo.uid, r.intent.getIntent(), r, r.userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); false /* isBindService */); } // If the foreground service is not started from TOP process, do not allow it to // have while-in-use location/camera/microphone access. if (!r.mAllowWhileInUsePermissionInFgs) { if (!r.isFgsAllowedWIU()) { Slog.w(TAG, "Foreground service started from background can not have " + "location/camera/microphone access: service " + r.shortInstanceName); } r.maybeLogFgsLogicChange(); if (!bypassBfslCheck) { logFgsBackgroundStart(r); if (r.mAllowStartForeground == REASON_DENIED if (!r.isFgsAllowedStart() && isBgFgsRestrictionEnabledForService) { final String msg = "Service.startForeground() not allowed due to " + "mAllowStartForeground false: service " Loading Loading @@ -2378,9 +2378,9 @@ public final class ActiveServices { // The logging of FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER event could // be deferred, make a copy of mAllowStartForeground and // mAllowWhileInUsePermissionInFgs. r.mAllowStartForegroundAtEntering = r.mAllowStartForeground; r.mAllowStartForegroundAtEntering = r.getFgsAllowStart(); r.mAllowWhileInUsePermissionInFgsAtEntering = r.mAllowWhileInUsePermissionInFgs; r.isFgsAllowedWIU(); r.mStartForegroundCount++; r.mFgsEnterTime = SystemClock.uptimeMillis(); if (!stopProcStatsOp) { Loading Loading @@ -2558,7 +2558,7 @@ public final class ActiveServices { policy.getForegroundServiceTypePolicyInfo(type, defaultToType); final @ForegroundServicePolicyCheckCode int code = policy.checkForegroundServiceTypePolicy( mAm.mContext, r.packageName, r.app.uid, r.app.getPid(), r.mAllowWhileInUsePermissionInFgs, policyInfo); r.isFgsAllowedWIU(), policyInfo); RuntimeException exception = null; switch (code) { case FGS_TYPE_POLICY_CHECK_DEPRECATED: { Loading Loading @@ -3744,8 +3744,7 @@ public final class ActiveServices { } } setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, userId, BackgroundStartPrivileges.NONE, true /* isBindService */, false /* isStartService */); BackgroundStartPrivileges.NONE, true /* isBindService */); if (s.app != null) { ProcessServiceRecord servicePsr = s.app.mServices; Loading Loading @@ -7443,54 +7442,80 @@ public final class ActiveServices { * @param callingUid caller app's uid. * @param intent intent to start/bind service. * @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.startForeground(). * @param isBindService True if it's called from bindService(). * @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) { BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) { @ReasonCode int allowWIU; @ReasonCode int allowStart; // If called from bindService(), do not update the actual fields, but instead // keep it in a separate set of fields. if (isBindService) { allowWIU = r.mAllowWIUInBindService; allowStart = r.mAllowStartInBindService; } else { allowWIU = r.mAllowWhileInUsePermissionInFgsReasonNoBinding; allowStart = r.mAllowStartForegroundNoBinding; } // Check DeviceConfig flag. if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) { if (!r.mAllowWhileInUsePermissionInFgs) { if (allowWIU == REASON_DENIED) { // BGFGS start restrictions are disabled. We're allowing while-in-use permissions. // Note REASON_OTHER since there's no other suitable reason. r.mAllowWhileInUsePermissionInFgsReason = REASON_OTHER; allowWIU = REASON_OTHER; } r.mAllowWhileInUsePermissionInFgs = true; } if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == REASON_DENIED)) { if ((allowWIU == REASON_DENIED) || (allowStart == REASON_DENIED)) { @ReasonCode final int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges); // 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 (!r.mAllowWhileInUsePermissionInFgs) { r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED); r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse; if (allowWIU == REASON_DENIED) { allowWIU = allowWhileInUse; } if (r.mAllowStartForeground == REASON_DENIED) { r.mAllowStartForeground = shouldAllowFgsStartForegroundWithBindingCheckLocked( if (allowStart == REASON_DENIED) { allowStart = shouldAllowFgsStartForegroundWithBindingCheckLocked( allowWhileInUse, callingPackage, callingPid, callingUid, intent, r, backgroundStartPrivileges, isBindService); } } if (isBindService) { r.mAllowWIUInBindService = allowWIU; r.mAllowStartInBindService = allowStart; } else { r.mAllowWhileInUsePermissionInFgsReasonNoBinding = allowWIU; r.mAllowStartForegroundNoBinding = allowStart; // Also do a binding client check, unless called from bindService(). if (r.mAllowWIUByBindings == REASON_DENIED) { r.mAllowWIUByBindings = shouldAllowFgsWhileInUsePermissionByBindingsLocked(callingUid); } if (r.mAllowStartByBindings == REASON_DENIED) { r.mAllowStartByBindings = r.mAllowWIUByBindings; } } } /** * Reset various while-in-use and BFSL related information. */ void resetFgsRestrictionLocked(ServiceRecord r) { r.mAllowWhileInUsePermissionInFgs = false; r.mAllowWhileInUsePermissionInFgsReason = REASON_DENIED; r.mAllowStartForeground = REASON_DENIED; r.clearFgsAllowWIU(); r.clearFgsAllowStart(); r.mInfoAllowStartForeground = null; r.mInfoTempFgsAllowListReason = null; r.mLoggedInfoAllowStartForeground = false; r.updateAllowUiJobScheduling(r.mAllowWhileInUsePermissionInFgs); r.updateAllowUiJobScheduling(r.isFgsAllowedWIU()); } boolean canStartForegroundServiceLocked(int callingPid, int callingUid, String callingPackage) { Loading Loading @@ -8062,10 +8087,10 @@ public final class ActiveServices { */ if (!r.mLoggedInfoAllowStartForeground) { final String msg = "Background started FGS: " + ((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ") + (r.isFgsAllowedStart() ? "Allowed " : "Disallowed ") + r.mInfoAllowStartForeground + (r.isShortFgs() ? " (Called on SHORT_SERVICE)" : ""); if (r.mAllowStartForeground != REASON_DENIED) { if (r.isFgsAllowedStart()) { if (ActivityManagerUtils.shouldSamplePackageForAtom(r.packageName, mAm.mConstants.mFgsStartAllowedLogSampleRate)) { Slog.wtfQuiet(TAG, msg); Loading Loading @@ -8105,8 +8130,8 @@ public final class ActiveServices { allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering; fgsStartReasonCode = r.mAllowStartForegroundAtEntering; } else { allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgs; fgsStartReasonCode = r.mAllowStartForeground; allowWhileInUsePermissionInFgs = r.isFgsAllowedWIU(); fgsStartReasonCode = r.getFgsAllowStart(); } final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0; Loading Loading @@ -8295,8 +8320,7 @@ public final class ActiveServices { r.mFgsEnterTime = SystemClock.uptimeMillis(); r.foregroundServiceType = options.mForegroundServiceTypes; setFgsRestrictionLocked(callingPackage, callingPid, callingUid, intent, r, userId, BackgroundStartPrivileges.NONE, false /* isBindService */, false /* isStartService */); BackgroundStartPrivileges.NONE, false /* isBindService */); final ProcessServiceRecord psr = callerApp.mServices; final boolean newService = psr.startService(r); // updateOomAdj. Loading
services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java +2 −2 Original line number Diff line number Diff line Loading @@ -479,8 +479,8 @@ public class ForegroundServiceTypeLoggerModule { r.appInfo.uid, r.shortInstanceName, fgsState, // FGS State r.mAllowWhileInUsePermissionInFgs, // allowWhileInUsePermissionInFgs r.mAllowStartForeground, // fgsStartReasonCode r.isFgsAllowedWIU(), // allowWhileInUsePermissionInFgs r.getFgsAllowStart(), // fgsStartReasonCode r.appInfo.targetSdkVersion, r.mRecentCallingUid, 0, // callerTargetSdkVersion Loading
services/core/java/com/android/server/am/OomAdjuster.java +1 −1 Original line number Diff line number Diff line Loading @@ -2222,7 +2222,7 @@ public class OomAdjuster { if (s.isForeground) { final int fgsType = s.foregroundServiceType; if (s.mAllowWhileInUsePermissionInFgs) { if (s.isFgsAllowedWIU()) { capabilityFromFGS |= (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; Loading
services/core/java/com/android/server/am/ServiceRecord.java +120 −8 Original line number Diff line number Diff line Loading @@ -21,9 +21,11 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BOUND_SERVICE; import static android.os.PowerExemptionManager.REASON_DENIED; import static android.os.PowerExemptionManager.reasonCodeToString; import static android.os.Process.INVALID_UID; import static com.android.internal.util.Preconditions.checkArgument; import static com.android.server.am.ActiveServices.TAG_SERVICE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; Loading Loading @@ -172,11 +174,11 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN private BackgroundStartPrivileges mBackgroundStartPrivilegesByStartMerged = BackgroundStartPrivileges.NONE; // allow while-in-use permissions in foreground service or not. // Reason code for allow while-in-use permissions in foreground service. // If it's not DENIED, while-in-use permissions are allowed. // while-in-use permissions in FGS started from background might be restricted. boolean mAllowWhileInUsePermissionInFgs; @PowerExemptionManager.ReasonCode int mAllowWhileInUsePermissionInFgsReason = REASON_DENIED; int mAllowWhileInUsePermissionInFgsReasonNoBinding = REASON_DENIED; // A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state. boolean mAllowWhileInUsePermissionInFgsAtEntering; Loading Loading @@ -205,15 +207,114 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // allow the service becomes foreground service? Service started from background may not be // allowed to become a foreground service. @PowerExemptionManager.ReasonCode int mAllowStartForeground = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartForegroundNoBinding = REASON_DENIED; // A copy of mAllowStartForeground's value when the service is entering FGS state. @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartForegroundAtEntering = REASON_DENIED; // Debug info why mAllowStartForeground is allowed or denied. String mInfoAllowStartForeground; // Debug info if mAllowStartForeground is allowed because of a temp-allowlist. ActivityManagerService.FgsTempAllowListItem mInfoTempFgsAllowListReason; // Is the same mInfoAllowStartForeground string has been logged before? Used for dedup. boolean mLoggedInfoAllowStartForeground; @PowerExemptionManager.ReasonCode int mAllowWIUInBindService = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowWIUByBindings = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartInBindService = REASON_DENIED; @PowerExemptionManager.ReasonCode int mAllowStartByBindings = REASON_DENIED; @PowerExemptionManager.ReasonCode int getFgsAllowWIU() { return mAllowWhileInUsePermissionInFgsReasonNoBinding != REASON_DENIED ? mAllowWhileInUsePermissionInFgsReasonNoBinding : mAllowWIUInBindService; } boolean isFgsAllowedWIU() { return getFgsAllowWIU() != REASON_DENIED; } @PowerExemptionManager.ReasonCode int getFgsAllowStart() { return mAllowStartForegroundNoBinding != REASON_DENIED ? mAllowStartForegroundNoBinding : mAllowStartInBindService; } boolean isFgsAllowedStart() { return getFgsAllowStart() != REASON_DENIED; } void clearFgsAllowWIU() { mAllowWhileInUsePermissionInFgsReasonNoBinding = REASON_DENIED; mAllowWIUInBindService = REASON_DENIED; mAllowWIUByBindings = REASON_DENIED; } void clearFgsAllowStart() { mAllowStartForegroundNoBinding = REASON_DENIED; mAllowStartInBindService = REASON_DENIED; mAllowStartByBindings = REASON_DENIED; } @PowerExemptionManager.ReasonCode int reasonOr(@PowerExemptionManager.ReasonCode int first, @PowerExemptionManager.ReasonCode int second) { return first != REASON_DENIED ? first : second; } boolean allowedChanged(@PowerExemptionManager.ReasonCode int first, @PowerExemptionManager.ReasonCode int second) { return (first == REASON_DENIED) != (second == REASON_DENIED); } String changeMessage(@PowerExemptionManager.ReasonCode int first, @PowerExemptionManager.ReasonCode int second) { return reasonOr(first, second) == REASON_DENIED ? "DENIED" : ("ALLOWED (" + reasonCodeToString(first) + "+" + reasonCodeToString(second) + ")"); } void maybeLogFgsLogicChange() { final int origWiu = reasonOr(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUInBindService); final int newWiu = reasonOr(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUByBindings); final int origStart = reasonOr(mAllowStartForegroundNoBinding, mAllowStartInBindService); final int newStart = reasonOr(mAllowStartForegroundNoBinding, mAllowStartByBindings); final boolean wiuChanged = allowedChanged(origWiu, newWiu); final boolean startChanged = allowedChanged(origStart, newStart); if (!wiuChanged && !startChanged) { return; } final String message = "FGS logic changed:" + (wiuChanged ? " [WIU changed]" : "") + (startChanged ? " [BFSL changed]" : "") + " OW:" // Orig-WIU + changeMessage(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUInBindService) + " NW:" // New-WIU + changeMessage(mAllowWhileInUsePermissionInFgsReasonNoBinding, mAllowWIUByBindings) + " OS:" // Orig-start + changeMessage(mAllowStartForegroundNoBinding, mAllowStartInBindService) + " NS:" // New-start + changeMessage(mAllowStartForegroundNoBinding, mAllowStartByBindings); Slog.wtf(TAG_SERVICE, message); } // The number of times Service.startForeground() is called, after this service record is // created. (i.e. due to "bound" or "start".) It never decreases, even when stopForeground() // is called. Loading Loading @@ -502,7 +603,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN ProtoUtils.toDuration(proto, ServiceRecordProto.RESTART_TIME, restartTime, now); proto.write(ServiceRecordProto.CREATED_FROM_FG, createdFromFg); proto.write(ServiceRecordProto.ALLOW_WHILE_IN_USE_PERMISSION_IN_FGS, mAllowWhileInUsePermissionInFgs); isFgsAllowedWIU()); if (startRequested || delayedStop || lastStartId != 0) { long startToken = proto.start(ServiceRecordProto.START); Loading Loading @@ -618,7 +719,13 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN pw.println(mBackgroundStartPrivilegesByStartMerged); } pw.print(prefix); pw.print("mAllowWhileInUsePermissionInFgsReason="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowWhileInUsePermissionInFgsReason)); pw.println(PowerExemptionManager.reasonCodeToString( mAllowWhileInUsePermissionInFgsReasonNoBinding)); pw.print(prefix); pw.print("mAllowWIUInBindService="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowWIUInBindService)); pw.print(prefix); pw.print("mAllowWIUByBindings="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowWIUByBindings)); pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling); pw.print(prefix); pw.print("recentCallingPackage="); Loading @@ -626,7 +733,12 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN pw.print(prefix); pw.print("recentCallingUid="); pw.println(mRecentCallingUid); pw.print(prefix); pw.print("allowStartForeground="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartForeground)); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartForegroundNoBinding)); pw.print(prefix); pw.print("mAllowStartInBindService="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartInBindService)); pw.print(prefix); pw.print("mAllowStartByBindings="); pw.println(PowerExemptionManager.reasonCodeToString(mAllowStartByBindings)); pw.print(prefix); pw.print("startForegroundCount="); pw.println(mStartForegroundCount); pw.print(prefix); pw.print("infoAllowStartForeground="); Loading