diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index e248007eca19c..a8046086a11de 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1019,6 +1019,24 @@ public final class ActiveServices { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants, callingUid, callingProcessName, callingPackage)); + // We want to allow scheduling user-initiated jobs when the app is running a + // foreground service that was started in the same conditions that allows for scheduling + // UI jobs. More explicitly, we want to allow scheduling UI jobs when the app is running + // an FGS that started when the app was in the TOP or a BAL-approved state. + final boolean isFgs = r.isForeground || r.fgRequired; + if (isFgs) { + // As of Android UDC, the conditions required for the while-in-use permissions + // are the same conditions that we want, so we piggyback on that logic. + // Use that as a shortcut if possible to avoid having to recheck all the conditions. + final boolean whileInUseAllowsUiJobScheduling = + ActivityManagerService.doesReasonCodeAllowSchedulingUserInitiatedJobs( + r.mAllowWhileInUsePermissionInFgsReason); + r.updateAllowUiJobScheduling(whileInUseAllowsUiJobScheduling + || mAm.canScheduleUserInitiatedJobs(callingUid, callingPid, callingPackage)); + } else { + r.updateAllowUiJobScheduling(false); + } + if (fgRequired) { // We are now effectively running a foreground service. synchronized (mAm.mProcessStats.mLock) { @@ -7362,26 +7380,12 @@ public final class ActiveServices { } else { allowWhileInUse = REASON_UNKNOWN; } - // We want to allow scheduling user-initiated jobs when the app is running a - // foreground service that was started in the same conditions that allows for scheduling - // UI jobs. More explicitly, we want to allow scheduling UI jobs when the app is running - // an FGS that started when the app was in the TOP or a BAL-approved state. - // As of Android UDC, the conditions required for the while-in-use permissions - // are the same conditions that we want, so we piggyback on that logic. - // We use that as a shortcut if possible so we don't have to recheck all the conditions. - final boolean isFgs = r.isForeground || r.fgRequired; - if (isFgs) { - r.updateAllowUiJobScheduling(ActivityManagerService - .doesReasonCodeAllowSchedulingUserInitiatedJobs(allowWhileInUse) - || mAm.canScheduleUserInitiatedJobs( - callingUid, callingPid, callingPackage, true)); - } else { - r.updateAllowUiJobScheduling(false); - } + r.mAllowWhileInUsePermissionInFgsReason = allowWhileInUse; } void resetFgsRestrictionLocked(ServiceRecord r) { r.mAllowWhileInUsePermissionInFgs = false; + r.mAllowWhileInUsePermissionInFgsReason = REASON_DENIED; r.mAllowStartForeground = REASON_DENIED; r.mInfoAllowStartForeground = null; r.mInfoTempFgsAllowListReason = null; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b32f8c973e6af..97d34b8dd7182 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6189,8 +6189,8 @@ public class ActivityManagerService extends IActivityManager.Stub final ProcessServiceRecord psr = pr.mServices; if (psr != null && psr.hasForegroundServices()) { - for (int s = psr.numberOfExecutingServices() - 1; s >= 0; --s) { - final ServiceRecord sr = psr.getExecutingServiceAt(s); + for (int s = psr.numberOfRunningServices() - 1; s >= 0; --s) { + final ServiceRecord sr = psr.getRunningServiceAt(s); if (sr.isForeground && sr.mAllowUiJobScheduling) { return true; } @@ -6205,12 +6205,7 @@ public class ActivityManagerService extends IActivityManager.Stub * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job}. */ // TODO(262260570): log allow reason to an atom - private boolean canScheduleUserInitiatedJobs(int uid, int pid, String pkgName) { - return canScheduleUserInitiatedJobs(uid, pid, pkgName, false); - } - - boolean canScheduleUserInitiatedJobs(int uid, int pid, String pkgName, - boolean skipWhileInUseCheck) { + boolean canScheduleUserInitiatedJobs(int uid, int pid, String pkgName) { synchronized (this) { final ProcessRecord processRecord; synchronized (mPidsSelfLocked) { @@ -6240,7 +6235,7 @@ public class ActivityManagerService extends IActivityManager.Stub // As of Android UDC, the conditions required to grant a while-in-use permission // covers the majority of those cases, and so we piggyback on that logic as the base. // Missing cases are added after. - if (!skipWhileInUseCheck && mServices.canAllowWhileInUsePermissionInFgsLocked( + if (mServices.canAllowWhileInUsePermissionInFgsLocked( pid, uid, pkgName, processRecord, backgroundStartPrivileges)) { return true; } diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index edf0dbd65ef2c..a875860f016f2 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -174,6 +174,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // allow while-in-use permissions in foreground service or not. // while-in-use permissions in FGS started from background might be restricted. boolean mAllowWhileInUsePermissionInFgs; + @PowerExemptionManager.ReasonCode + int mAllowWhileInUsePermissionInFgsReason; // A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state. boolean mAllowWhileInUsePermissionInFgsAtEntering; /** Allow scheduling user-initiated jobs from the background. */ @@ -609,6 +611,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs="); pw.println(mAllowWhileInUsePermissionInFgs); + pw.print(prefix); pw.print("mAllowWhileInUsePermissionInFgsReason="); + pw.println(mAllowWhileInUsePermissionInFgsReason); pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling); pw.print(prefix); pw.print("recentCallingPackage="); pw.println(mRecentCallingPackage);