Loading apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -1259,10 +1259,14 @@ class JobConcurrencyManager { final BackgroundStartPrivileges bsp = activityManagerInternal.getBackgroundStartPrivileges(uid); final boolean balAllowed = bsp.allowsBackgroundActivityStarts(); if (DEBUG) { Slog.d(TAG, "Job " + job.toShortString() + " bal state: " + bsp); Slog.d(TAG, "Job " + job.toShortString() + " bsp state: " + bsp); } // Intentionally use the background activity start BSP here instead of // the full BAL check since the former is transient and better indicates that the // user recently interacted with the app, while the latter includes // permanent exceptions that don't warrant bypassing normal concurrency policy. final boolean balAllowed = bsp.allowsBackgroundActivityStarts(); cachedPrivilegedState.put(uid, balAllowed ? PRIVILEGED_STATE_BAL : PRIVILEGED_STATE_NONE); return balAllowed; Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +41 −23 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.BackgroundStartPrivileges; import android.app.IUidObserver; import android.app.compat.CompatChanges; import android.app.job.IJobScheduler; Loading Loading @@ -3782,7 +3781,8 @@ public class JobSchedulerService extends com.android.server.SystemService return canPersist; } private int validateJob(@NonNull JobInfo job, int callingUid, int sourceUserId, private int validateJob(@NonNull JobInfo job, int callingUid, int callingPid, int sourceUserId, @Nullable String sourcePkgName, @Nullable JobWorkItem jobWorkItem) { final boolean rejectNegativeNetworkEstimates = CompatChanges.isChangeEnabled( JobInfo.REJECT_NEGATIVE_NETWORK_ESTIMATES, callingUid); Loading Loading @@ -3815,6 +3815,8 @@ public class JobSchedulerService extends com.android.server.SystemService } // We aim to check the permission of both the source and calling app so that apps // don't attempt to bypass the permission by using other apps to do the work. boolean isInStateToScheduleUiJobSource = false; final String callingPkgName = job.getService().getPackageName(); if (sourceUid != -1) { // Check the permission of the source app. final int sourceResult = Loading @@ -3822,8 +3824,13 @@ public class JobSchedulerService extends com.android.server.SystemService if (sourceResult != JobScheduler.RESULT_SUCCESS) { return sourceResult; } final int sourcePid = callingUid == sourceUid && callingPkgName.equals(sourcePkgName) ? callingPid : -1; isInStateToScheduleUiJobSource = isInStateToScheduleUserInitiatedJobs( sourceUid, sourcePid, sourcePkgName); } final String callingPkgName = job.getService().getPackageName(); boolean isInStateToScheduleUiJobCalling = false; if (callingUid != sourceUid || !callingPkgName.equals(sourcePkgName)) { // Source app is different from calling app. Make sure the calling app also has // the permission. Loading @@ -3832,27 +3839,19 @@ public class JobSchedulerService extends com.android.server.SystemService if (callingResult != JobScheduler.RESULT_SUCCESS) { return callingResult; } // Avoid rechecking the state if the source app is able to schedule the job. if (!isInStateToScheduleUiJobSource) { isInStateToScheduleUiJobCalling = isInStateToScheduleUserInitiatedJobs( callingUid, callingPid, callingPkgName); } final int uid = sourceUid != -1 ? sourceUid : callingUid; final int procState = mActivityManagerInternal.getUidProcessState(uid); if (DEBUG) { Slog.d(TAG, "Uid " + uid + " proc state=" + ActivityManager.procStateToString(procState)); } if (procState != ActivityManager.PROCESS_STATE_TOP) { final BackgroundStartPrivileges bsp = mActivityManagerInternal.getBackgroundStartPrivileges(uid); if (DEBUG) { Slog.d(TAG, "Uid " + uid + ": " + bsp); } if (!bsp.allowsBackgroundActivityStarts()) { Slog.e(TAG, "Uid " + uid + " not in a state to schedule user-initiated jobs"); if (!isInStateToScheduleUiJobSource && !isInStateToScheduleUiJobCalling) { Slog.e(TAG, "Uid(s) " + sourceUid + "/" + callingUid + " not in a state to schedule user-initiated jobs"); return JobScheduler.RESULT_FAILURE; } } } if (jobWorkItem != null) { jobWorkItem.enforceValidity(rejectNegativeNetworkEstimates); if (jobWorkItem.getEstimatedNetworkDownloadBytes() != JobInfo.NETWORK_BYTES_UNKNOWN Loading Loading @@ -3896,6 +3895,24 @@ public class JobSchedulerService extends com.android.server.SystemService return JobScheduler.RESULT_SUCCESS; } private boolean isInStateToScheduleUserInitiatedJobs(int uid, int pid, String pkgName) { final int procState = mActivityManagerInternal.getUidProcessState(uid); if (DEBUG) { Slog.d(TAG, "Uid " + uid + " proc state=" + ActivityManager.procStateToString(procState)); } if (procState == ActivityManager.PROCESS_STATE_TOP) { return true; } final boolean canScheduleUiJobsInBg = mActivityManagerInternal.canScheduleUserInitiatedJobs(uid, pid, pkgName); if (DEBUG) { Slog.d(TAG, "Uid " + uid + " AM.canScheduleUserInitiatedJobs= " + canScheduleUiJobsInBg); } return canScheduleUiJobsInBg; } // IJobScheduler implementation @Override public int schedule(String namespace, JobInfo job) throws RemoteException { Loading @@ -3908,7 +3925,7 @@ public class JobSchedulerService extends com.android.server.SystemService enforceValidJobRequest(uid, pid, job); final int result = validateJob(job, uid, -1, null, null); final int result = validateJob(job, uid, pid, -1, null, null); if (result != JobScheduler.RESULT_SUCCESS) { return result; } Loading Loading @@ -3941,7 +3958,7 @@ public class JobSchedulerService extends com.android.server.SystemService throw new NullPointerException("work is null"); } final int result = validateJob(job, uid, -1, null, work); final int result = validateJob(job, uid, pid, -1, null, work); if (result != JobScheduler.RESULT_SUCCESS) { return result; } Loading @@ -3963,6 +3980,7 @@ public class JobSchedulerService extends com.android.server.SystemService public int scheduleAsPackage(String namespace, JobInfo job, String packageName, int userId, String tag) throws RemoteException { final int callerUid = Binder.getCallingUid(); final int callerPid = Binder.getCallingPid(); if (DEBUG) { Slog.d(TAG, "Caller uid " + callerUid + " scheduling job: " + job.toString() + " on behalf of " + packageName + "/"); Loading @@ -3979,7 +3997,7 @@ public class JobSchedulerService extends com.android.server.SystemService + " not permitted to schedule jobs for other apps"); } int result = validateJob(job, callerUid, userId, packageName, null); int result = validateJob(job, callerUid, callerPid, userId, packageName, null); if (result != JobScheduler.RESULT_SUCCESS) { return result; } Loading core/java/android/app/ActivityManagerInternal.java +6 −0 Original line number Diff line number Diff line Loading @@ -474,6 +474,12 @@ public abstract class ActivityManagerInternal { public abstract BackgroundStartPrivileges getBackgroundStartPrivileges(int uid); public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing); /** * Returns whether the app is in a state where it is allowed to schedule a * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job}. */ public abstract boolean canScheduleUserInitiatedJobs(int uid, int pid, String pkgName); /** @see com.android.server.am.ActivityManagerService#monitor */ public abstract void monitor(); Loading services/core/java/com/android/server/am/ActiveServices.java +17 −9 Original line number Diff line number Diff line Loading @@ -7322,7 +7322,7 @@ public final class ActiveServices { if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == REASON_DENIED)) { final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, r, backgroundStartPrivileges, callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges, isBindService); if (!r.mAllowWhileInUsePermissionInFgs) { r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED); Loading @@ -7349,7 +7349,7 @@ public final class ActiveServices { return true; } final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, null /* serviceRecord */, callingPackage, callingPid, callingUid, null /* targetProcess */, BackgroundStartPrivileges.NONE, false); @ReasonCode int allowStartFgs = shouldAllowFgsStartForegroundNoBindingCheckLocked( allowWhileInUse, callingPid, callingUid, callingPackage, null /* targetService */, Loading @@ -7366,13 +7366,14 @@ public final class ActiveServices { /** * Should allow while-in-use permissions in FGS or not. * A typical BG started FGS is not allowed to have while-in-use permissions. * * @param callingPackage caller app's package name. * @param callingUid caller app's uid. * @param targetService the service to start. * @param targetProcess the process of the service to start. * @return {@link ReasonCode} */ private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage, int callingPid, int callingUid, @Nullable ServiceRecord targetService, int callingPid, int callingUid, @Nullable ProcessRecord targetProcess, BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) { int ret = REASON_DENIED; Loading Loading @@ -7440,8 +7441,8 @@ public final class ActiveServices { } if (ret == REASON_DENIED) { if (targetService != null && targetService.app != null) { ActiveInstrumentation instr = targetService.app.getActiveInstrumentation(); if (targetProcess != null) { ActiveInstrumentation instr = targetProcess.getActiveInstrumentation(); if (instr != null && instr.mHasBackgroundActivityStartsPermission) { ret = REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION; } Loading Loading @@ -7526,7 +7527,7 @@ public final class ActiveServices { final @ReasonCode int allowWhileInUse2 = shouldAllowFgsWhileInUsePermissionLocked( clientPackageName, clientPid, clientUid, null /* serviceRecord */, clientPid, clientUid, null /* targetProcess */, BackgroundStartPrivileges.NONE, false); final @ReasonCode int allowStartFgs = shouldAllowFgsStartForegroundNoBindingCheckLocked( Loading Loading @@ -7946,11 +7947,18 @@ public final class ActiveServices { boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid, String callingPackage) { return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid, /* targetService */ null, /* targetProcess */ null, BackgroundStartPrivileges.NONE, false) != REASON_DENIED; } boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid, String callingPackage, @Nullable ProcessRecord targetProcess, @NonNull BackgroundStartPrivileges backgroundStartPrivileges) { return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid, targetProcess, backgroundStartPrivileges, false) != REASON_DENIED; } /** * Checks if a given packageName belongs to a given uid. * @param packageName the package of the caller Loading services/core/java/com/android/server/am/ActivityManagerConstants.java +23 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,8 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_PROCESS_CRASH_COUNT_LIMIT = "process_crash_count_limit"; static final String KEY_BOOT_TIME_TEMP_ALLOWLIST_DURATION = "boot_time_temp_allowlist_duration"; static final String KEY_FG_TO_BG_FGS_GRACE_DURATION = "fg_to_bg_fgs_grace_duration"; static final String KEY_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION = "vis_to_invis_uij_schedule_grace_duration"; static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout"; static final String KEY_FGS_ATOM_SAMPLE_RATE = "fgs_atom_sample_rate"; static final String KEY_FGS_START_ALLOWED_LOG_SAMPLE_RATE = "fgs_start_allowed_log_sample_rate"; Loading Loading @@ -191,6 +193,8 @@ final class ActivityManagerConstants extends ContentObserver { private static final int DEFAULT_PROCESS_CRASH_COUNT_LIMIT = 12; private static final int DEFAULT_BOOT_TIME_TEMP_ALLOWLIST_DURATION = 20 * 1000; private static final long DEFAULT_FG_TO_BG_FGS_GRACE_DURATION = 5 * 1000; private static final long DEFAULT_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION = DEFAULT_FG_TO_BG_FGS_GRACE_DURATION; private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000; private static final float DEFAULT_FGS_ATOM_SAMPLE_RATE = 1; // 100 % private static final float DEFAULT_FGS_START_ALLOWED_LOG_SAMPLE_RATE = 0.25f; // 25% Loading Loading @@ -679,6 +683,15 @@ final class ActivityManagerConstants extends ContentObserver { */ volatile long mFgToBgFgsGraceDuration = DEFAULT_FG_TO_BG_FGS_GRACE_DURATION; /** * The grace period in milliseconds to allow a process to schedule a * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job} * after switching from visible to a non-visible state. * Currently it's only applicable to its activities. */ volatile long mVisibleToInvisibleUijScheduleGraceDurationMs = DEFAULT_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION; /** * When service started from background, before the timeout it can be promoted to FGS by calling * Service.startForeground(). Loading Loading @@ -1123,6 +1136,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_FG_TO_BG_FGS_GRACE_DURATION: updateFgToBgFgsGraceDuration(); break; case KEY_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION: updateFgToBgFgsGraceDuration(); break; case KEY_FGS_START_FOREGROUND_TIMEOUT: updateFgsStartForegroundTimeout(); break; Loading Loading @@ -1598,6 +1614,13 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_FG_TO_BG_FGS_GRACE_DURATION); } private void updateVisibleToInvisibleUijScheduleGraceDuration() { mVisibleToInvisibleUijScheduleGraceDurationMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION, DEFAULT_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION); } private void updateFgsStartForegroundTimeout() { mFgsStartForegroundTimeoutMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -1259,10 +1259,14 @@ class JobConcurrencyManager { final BackgroundStartPrivileges bsp = activityManagerInternal.getBackgroundStartPrivileges(uid); final boolean balAllowed = bsp.allowsBackgroundActivityStarts(); if (DEBUG) { Slog.d(TAG, "Job " + job.toShortString() + " bal state: " + bsp); Slog.d(TAG, "Job " + job.toShortString() + " bsp state: " + bsp); } // Intentionally use the background activity start BSP here instead of // the full BAL check since the former is transient and better indicates that the // user recently interacted with the app, while the latter includes // permanent exceptions that don't warrant bypassing normal concurrency policy. final boolean balAllowed = bsp.allowsBackgroundActivityStarts(); cachedPrivilegedState.put(uid, balAllowed ? PRIVILEGED_STATE_BAL : PRIVILEGED_STATE_NONE); return balAllowed; Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +41 −23 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.BackgroundStartPrivileges; import android.app.IUidObserver; import android.app.compat.CompatChanges; import android.app.job.IJobScheduler; Loading Loading @@ -3782,7 +3781,8 @@ public class JobSchedulerService extends com.android.server.SystemService return canPersist; } private int validateJob(@NonNull JobInfo job, int callingUid, int sourceUserId, private int validateJob(@NonNull JobInfo job, int callingUid, int callingPid, int sourceUserId, @Nullable String sourcePkgName, @Nullable JobWorkItem jobWorkItem) { final boolean rejectNegativeNetworkEstimates = CompatChanges.isChangeEnabled( JobInfo.REJECT_NEGATIVE_NETWORK_ESTIMATES, callingUid); Loading Loading @@ -3815,6 +3815,8 @@ public class JobSchedulerService extends com.android.server.SystemService } // We aim to check the permission of both the source and calling app so that apps // don't attempt to bypass the permission by using other apps to do the work. boolean isInStateToScheduleUiJobSource = false; final String callingPkgName = job.getService().getPackageName(); if (sourceUid != -1) { // Check the permission of the source app. final int sourceResult = Loading @@ -3822,8 +3824,13 @@ public class JobSchedulerService extends com.android.server.SystemService if (sourceResult != JobScheduler.RESULT_SUCCESS) { return sourceResult; } final int sourcePid = callingUid == sourceUid && callingPkgName.equals(sourcePkgName) ? callingPid : -1; isInStateToScheduleUiJobSource = isInStateToScheduleUserInitiatedJobs( sourceUid, sourcePid, sourcePkgName); } final String callingPkgName = job.getService().getPackageName(); boolean isInStateToScheduleUiJobCalling = false; if (callingUid != sourceUid || !callingPkgName.equals(sourcePkgName)) { // Source app is different from calling app. Make sure the calling app also has // the permission. Loading @@ -3832,27 +3839,19 @@ public class JobSchedulerService extends com.android.server.SystemService if (callingResult != JobScheduler.RESULT_SUCCESS) { return callingResult; } // Avoid rechecking the state if the source app is able to schedule the job. if (!isInStateToScheduleUiJobSource) { isInStateToScheduleUiJobCalling = isInStateToScheduleUserInitiatedJobs( callingUid, callingPid, callingPkgName); } final int uid = sourceUid != -1 ? sourceUid : callingUid; final int procState = mActivityManagerInternal.getUidProcessState(uid); if (DEBUG) { Slog.d(TAG, "Uid " + uid + " proc state=" + ActivityManager.procStateToString(procState)); } if (procState != ActivityManager.PROCESS_STATE_TOP) { final BackgroundStartPrivileges bsp = mActivityManagerInternal.getBackgroundStartPrivileges(uid); if (DEBUG) { Slog.d(TAG, "Uid " + uid + ": " + bsp); } if (!bsp.allowsBackgroundActivityStarts()) { Slog.e(TAG, "Uid " + uid + " not in a state to schedule user-initiated jobs"); if (!isInStateToScheduleUiJobSource && !isInStateToScheduleUiJobCalling) { Slog.e(TAG, "Uid(s) " + sourceUid + "/" + callingUid + " not in a state to schedule user-initiated jobs"); return JobScheduler.RESULT_FAILURE; } } } if (jobWorkItem != null) { jobWorkItem.enforceValidity(rejectNegativeNetworkEstimates); if (jobWorkItem.getEstimatedNetworkDownloadBytes() != JobInfo.NETWORK_BYTES_UNKNOWN Loading Loading @@ -3896,6 +3895,24 @@ public class JobSchedulerService extends com.android.server.SystemService return JobScheduler.RESULT_SUCCESS; } private boolean isInStateToScheduleUserInitiatedJobs(int uid, int pid, String pkgName) { final int procState = mActivityManagerInternal.getUidProcessState(uid); if (DEBUG) { Slog.d(TAG, "Uid " + uid + " proc state=" + ActivityManager.procStateToString(procState)); } if (procState == ActivityManager.PROCESS_STATE_TOP) { return true; } final boolean canScheduleUiJobsInBg = mActivityManagerInternal.canScheduleUserInitiatedJobs(uid, pid, pkgName); if (DEBUG) { Slog.d(TAG, "Uid " + uid + " AM.canScheduleUserInitiatedJobs= " + canScheduleUiJobsInBg); } return canScheduleUiJobsInBg; } // IJobScheduler implementation @Override public int schedule(String namespace, JobInfo job) throws RemoteException { Loading @@ -3908,7 +3925,7 @@ public class JobSchedulerService extends com.android.server.SystemService enforceValidJobRequest(uid, pid, job); final int result = validateJob(job, uid, -1, null, null); final int result = validateJob(job, uid, pid, -1, null, null); if (result != JobScheduler.RESULT_SUCCESS) { return result; } Loading Loading @@ -3941,7 +3958,7 @@ public class JobSchedulerService extends com.android.server.SystemService throw new NullPointerException("work is null"); } final int result = validateJob(job, uid, -1, null, work); final int result = validateJob(job, uid, pid, -1, null, work); if (result != JobScheduler.RESULT_SUCCESS) { return result; } Loading @@ -3963,6 +3980,7 @@ public class JobSchedulerService extends com.android.server.SystemService public int scheduleAsPackage(String namespace, JobInfo job, String packageName, int userId, String tag) throws RemoteException { final int callerUid = Binder.getCallingUid(); final int callerPid = Binder.getCallingPid(); if (DEBUG) { Slog.d(TAG, "Caller uid " + callerUid + " scheduling job: " + job.toString() + " on behalf of " + packageName + "/"); Loading @@ -3979,7 +3997,7 @@ public class JobSchedulerService extends com.android.server.SystemService + " not permitted to schedule jobs for other apps"); } int result = validateJob(job, callerUid, userId, packageName, null); int result = validateJob(job, callerUid, callerPid, userId, packageName, null); if (result != JobScheduler.RESULT_SUCCESS) { return result; } Loading
core/java/android/app/ActivityManagerInternal.java +6 −0 Original line number Diff line number Diff line Loading @@ -474,6 +474,12 @@ public abstract class ActivityManagerInternal { public abstract BackgroundStartPrivileges getBackgroundStartPrivileges(int uid); public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing); /** * Returns whether the app is in a state where it is allowed to schedule a * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job}. */ public abstract boolean canScheduleUserInitiatedJobs(int uid, int pid, String pkgName); /** @see com.android.server.am.ActivityManagerService#monitor */ public abstract void monitor(); Loading
services/core/java/com/android/server/am/ActiveServices.java +17 −9 Original line number Diff line number Diff line Loading @@ -7322,7 +7322,7 @@ public final class ActiveServices { if (!r.mAllowWhileInUsePermissionInFgs || (r.mAllowStartForeground == REASON_DENIED)) { final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, r, backgroundStartPrivileges, callingPackage, callingPid, callingUid, r.app, backgroundStartPrivileges, isBindService); if (!r.mAllowWhileInUsePermissionInFgs) { r.mAllowWhileInUsePermissionInFgs = (allowWhileInUse != REASON_DENIED); Loading @@ -7349,7 +7349,7 @@ public final class ActiveServices { return true; } final @ReasonCode int allowWhileInUse = shouldAllowFgsWhileInUsePermissionLocked( callingPackage, callingPid, callingUid, null /* serviceRecord */, callingPackage, callingPid, callingUid, null /* targetProcess */, BackgroundStartPrivileges.NONE, false); @ReasonCode int allowStartFgs = shouldAllowFgsStartForegroundNoBindingCheckLocked( allowWhileInUse, callingPid, callingUid, callingPackage, null /* targetService */, Loading @@ -7366,13 +7366,14 @@ public final class ActiveServices { /** * Should allow while-in-use permissions in FGS or not. * A typical BG started FGS is not allowed to have while-in-use permissions. * * @param callingPackage caller app's package name. * @param callingUid caller app's uid. * @param targetService the service to start. * @param targetProcess the process of the service to start. * @return {@link ReasonCode} */ private @ReasonCode int shouldAllowFgsWhileInUsePermissionLocked(String callingPackage, int callingPid, int callingUid, @Nullable ServiceRecord targetService, int callingPid, int callingUid, @Nullable ProcessRecord targetProcess, BackgroundStartPrivileges backgroundStartPrivileges, boolean isBindService) { int ret = REASON_DENIED; Loading Loading @@ -7440,8 +7441,8 @@ public final class ActiveServices { } if (ret == REASON_DENIED) { if (targetService != null && targetService.app != null) { ActiveInstrumentation instr = targetService.app.getActiveInstrumentation(); if (targetProcess != null) { ActiveInstrumentation instr = targetProcess.getActiveInstrumentation(); if (instr != null && instr.mHasBackgroundActivityStartsPermission) { ret = REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION; } Loading Loading @@ -7526,7 +7527,7 @@ public final class ActiveServices { final @ReasonCode int allowWhileInUse2 = shouldAllowFgsWhileInUsePermissionLocked( clientPackageName, clientPid, clientUid, null /* serviceRecord */, clientPid, clientUid, null /* targetProcess */, BackgroundStartPrivileges.NONE, false); final @ReasonCode int allowStartFgs = shouldAllowFgsStartForegroundNoBindingCheckLocked( Loading Loading @@ -7946,11 +7947,18 @@ public final class ActiveServices { boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid, String callingPackage) { return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid, /* targetService */ null, /* targetProcess */ null, BackgroundStartPrivileges.NONE, false) != REASON_DENIED; } boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid, String callingPackage, @Nullable ProcessRecord targetProcess, @NonNull BackgroundStartPrivileges backgroundStartPrivileges) { return shouldAllowFgsWhileInUsePermissionLocked(callingPackage, callingPid, callingUid, targetProcess, backgroundStartPrivileges, false) != REASON_DENIED; } /** * Checks if a given packageName belongs to a given uid. * @param packageName the package of the caller Loading
services/core/java/com/android/server/am/ActivityManagerConstants.java +23 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,8 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_PROCESS_CRASH_COUNT_LIMIT = "process_crash_count_limit"; static final String KEY_BOOT_TIME_TEMP_ALLOWLIST_DURATION = "boot_time_temp_allowlist_duration"; static final String KEY_FG_TO_BG_FGS_GRACE_DURATION = "fg_to_bg_fgs_grace_duration"; static final String KEY_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION = "vis_to_invis_uij_schedule_grace_duration"; static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout"; static final String KEY_FGS_ATOM_SAMPLE_RATE = "fgs_atom_sample_rate"; static final String KEY_FGS_START_ALLOWED_LOG_SAMPLE_RATE = "fgs_start_allowed_log_sample_rate"; Loading Loading @@ -191,6 +193,8 @@ final class ActivityManagerConstants extends ContentObserver { private static final int DEFAULT_PROCESS_CRASH_COUNT_LIMIT = 12; private static final int DEFAULT_BOOT_TIME_TEMP_ALLOWLIST_DURATION = 20 * 1000; private static final long DEFAULT_FG_TO_BG_FGS_GRACE_DURATION = 5 * 1000; private static final long DEFAULT_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION = DEFAULT_FG_TO_BG_FGS_GRACE_DURATION; private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000; private static final float DEFAULT_FGS_ATOM_SAMPLE_RATE = 1; // 100 % private static final float DEFAULT_FGS_START_ALLOWED_LOG_SAMPLE_RATE = 0.25f; // 25% Loading Loading @@ -679,6 +683,15 @@ final class ActivityManagerConstants extends ContentObserver { */ volatile long mFgToBgFgsGraceDuration = DEFAULT_FG_TO_BG_FGS_GRACE_DURATION; /** * The grace period in milliseconds to allow a process to schedule a * {@link android.app.job.JobInfo.Builder#setUserInitiated(boolean) user-initiated job} * after switching from visible to a non-visible state. * Currently it's only applicable to its activities. */ volatile long mVisibleToInvisibleUijScheduleGraceDurationMs = DEFAULT_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION; /** * When service started from background, before the timeout it can be promoted to FGS by calling * Service.startForeground(). Loading Loading @@ -1123,6 +1136,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_FG_TO_BG_FGS_GRACE_DURATION: updateFgToBgFgsGraceDuration(); break; case KEY_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION: updateFgToBgFgsGraceDuration(); break; case KEY_FGS_START_FOREGROUND_TIMEOUT: updateFgsStartForegroundTimeout(); break; Loading Loading @@ -1598,6 +1614,13 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_FG_TO_BG_FGS_GRACE_DURATION); } private void updateVisibleToInvisibleUijScheduleGraceDuration() { mVisibleToInvisibleUijScheduleGraceDurationMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION, DEFAULT_VISIBLE_TO_INVISIBLE_UIJ_SCHEDULE_GRACE_DURATION); } private void updateFgsStartForegroundTimeout() { mFgsStartForegroundTimeoutMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, Loading