diff options
3 files changed, 52 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 461103ee4355..8fe61e719817 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -73,6 +73,7 @@ import static android.os.PowerExemptionManager.REASON_SYSTEM_MODULE; import static android.os.PowerExemptionManager.REASON_SYSTEM_UID; import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE; import static android.os.PowerExemptionManager.REASON_UID_VISIBLE; +import static android.os.PowerExemptionManager.REASON_UNKNOWN; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.os.PowerExemptionManager.getReasonCodeFromProcState; import static android.os.PowerExemptionManager.reasonCodeToString; @@ -7319,9 +7320,10 @@ public final class ActiveServices { r.mAllowWhileInUsePermissionInFgs = true; } + final @ReasonCode int allowWhileInUse; if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == REASON_DENIED)) { - final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( + allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges, isBindService); if (!r.mAllowWhileInUsePermissionInFgs) { @@ -7332,6 +7334,24 @@ public final class ActiveServices { allowWhileInUse, callingPackage, callingPid, callingUid, intent, r, backgroundStartPrivileges, isBindService); } + } 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); } } @@ -7342,6 +7362,7 @@ public final class ActiveServices { r.mInfoTempFgsAllowListReason = null; r.mLoggedInfoAllowStartForeground = false; r.mLastSetFgsRestrictionTime = 0; + r.updateAllowUiJobScheduling(r.mAllowWhileInUsePermissionInFgs); } boolean canStartForegroundServiceLocked(int callingPid, int callingUid, String callingPackage) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 65c4d7581b4b..f2b6306aab5b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6563,7 +6563,7 @@ public class ActivityManagerService extends IActivityManager.Stub * This is a shortcut and <b>DOES NOT</b> include all reasons. * Use {@link #canScheduleUserInitiatedJobs(int, int, String)} to cover all cases. */ - private boolean doesReasonCodeAllowSchedulingUserInitiatedJobs(int reasonCode) { + static boolean doesReasonCodeAllowSchedulingUserInitiatedJobs(int reasonCode) { switch (reasonCode) { case REASON_PROC_STATE_PERSISTENT: case REASON_PROC_STATE_PERSISTENT_UI: @@ -6621,6 +6621,16 @@ 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); + if (sr.isForeground && sr.mAllowUiJobScheduling) { + return true; + } + } + } + return false; } @@ -6630,6 +6640,11 @@ public class ActivityManagerService extends IActivityManager.Stub */ // 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) { synchronized (this) { final ProcessRecord processRecord; synchronized (mPidsSelfLocked) { @@ -6659,7 +6674,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 (mServices.canAllowWhileInUsePermissionInFgsLocked( + if (!skipWhileInUseCheck && 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 4defdc6976e1..18ef66febe89 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -176,6 +176,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN boolean mAllowWhileInUsePermissionInFgs; // A copy of mAllowWhileInUsePermissionInFgs's value when the service is entering FGS state. boolean mAllowWhileInUsePermissionInFgsAtEntering; + /** Allow scheduling user-initiated jobs from the background. */ + boolean mAllowUiJobScheduling; // the most recent package that start/bind this service. String mRecentCallingPackage; @@ -607,6 +609,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs="); pw.println(mAllowWhileInUsePermissionInFgs); + pw.print(prefix); pw.print("allowUiJobScheduling="); pw.println(mAllowUiJobScheduling); pw.print(prefix); pw.print("recentCallingPackage="); pw.println(mRecentCallingPackage); pw.print(prefix); pw.print("recentCallingUid="); @@ -1024,7 +1027,17 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN ams.mConstants.SERVICE_BG_ACTIVITY_START_TIMEOUT); } + void updateAllowUiJobScheduling(boolean allowUiJobScheduling) { + if (mAllowUiJobScheduling == allowUiJobScheduling) { + return; + } + mAllowUiJobScheduling = allowUiJobScheduling; + } + private void setAllowedBgActivityStartsByStart(BackgroundStartPrivileges newValue) { + if (mBackgroundStartPrivilegesByStartMerged == newValue) { + return; + } mBackgroundStartPrivilegesByStartMerged = newValue; updateParentProcessBgActivityStartsToken(); } |