diff options
4 files changed, 191 insertions, 55 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index c1239d53058c..502e0ecac6fb 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -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; @@ -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); @@ -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; @@ -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 { @@ -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 { @@ -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) { @@ -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; @@ -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 " @@ -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) { @@ -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: { @@ -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; @@ -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) { @@ -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); @@ -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; @@ -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. diff --git a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java index 38e7371e7075..4f5b5e1fbd68 100644 --- a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java +++ b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java @@ -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 diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index e51fc0a2cef7..c99644cb927f 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -2218,7 +2218,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; diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 50fe6d71d26e..aabab61c36f4 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -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; @@ -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; @@ -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. @@ -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); @@ -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="); @@ -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="); |