Loading apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +109 −43 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.UidObserver; import android.app.compat.CompatChanges; import android.app.job.JobInfo; import android.app.usage.UsageEvents; import android.app.usage.UsageStatsManagerInternal; Loading @@ -54,6 +53,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.Trace; import android.os.UserHandle; import android.provider.DeviceConfig; Loading @@ -74,6 +74,7 @@ import com.android.internal.util.ArrayUtils; import com.android.server.AppSchedulingModuleThread; import com.android.server.LocalServices; import com.android.server.PowerAllowlistInternal; import com.android.server.compat.PlatformCompat; import com.android.server.job.ConstantsProto; import com.android.server.job.Flags; import com.android.server.job.JobSchedulerService; Loading Loading @@ -157,6 +158,15 @@ public final class QuotaController extends StateController { @Overridable // The change can be overridden in user build. static final long OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS = 374323858L; /** * When enabled this change id overrides the default quota parameters adjustment. */ @VisibleForTesting @ChangeId @Disabled // Disabled by default @Overridable // The change can be overridden in user build. static final long OVERRIDE_QUOTA_ADJUST_DEFAULT_CONSTANTS = 378129159L; @VisibleForTesting static class ExecutionStats { /** Loading Loading @@ -536,6 +546,8 @@ public final class QuotaController extends StateController { */ private final SparseSetArray<String> mSystemInstallers = new SparseSetArray<>(); private final PlatformCompat mPlatformCompat; /** An app has reached its quota. The message should contain a {@link UserPackage} object. */ @VisibleForTesting static final int MSG_REACHED_TIME_QUOTA = 0; Loading Loading @@ -587,6 +599,13 @@ public final class QuotaController extends StateController { PowerAllowlistInternal pai = LocalServices.getService(PowerAllowlistInternal.class); pai.registerTempAllowlistChangeListener(new TempAllowlistTracker()); mPlatformCompat = (PlatformCompat) ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); if (Flags.adjustQuotaDefaultConstants()) { mPlatformCompat.registerListener(OVERRIDE_QUOTA_ADJUST_DEFAULT_CONSTANTS, (packageName) -> handleQuotaDefaultConstantsCompatChange()); } try { ActivityManager.getService().registerUidObserver(new QcUidObserver(), ActivityManager.UID_OBSERVER_PROCSTATE, Loading Loading @@ -651,8 +670,9 @@ public final class QuotaController extends StateController { final int uid = jobStatus.getSourceUid(); if ((!Flags.enforceQuotaPolicyToTopStartedJobs() || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, uid)) && mTopAppCache.get(uid)) { || mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, uid)) && mTopAppCache.get(uid)) { if (DEBUG) { Slog.d(TAG, jobStatus.toShortString() + " is top started job"); } Loading Loading @@ -690,8 +710,8 @@ public final class QuotaController extends StateController { } } if (!Flags.enforceQuotaPolicyToTopStartedJobs() || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { || mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { mTopStartedJobs.remove(jobStatus); } } Loading Loading @@ -805,8 +825,8 @@ public final class QuotaController extends StateController { /** @return true if the job was started while the app was in the TOP state. */ private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) { if (!Flags.enforceQuotaPolicyToTopStartedJobs() || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { || mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { return mTopStartedJobs.contains(jobStatus); } Loading Loading @@ -1102,6 +1122,7 @@ public final class QuotaController extends StateController { final int standbyBucket) { final long baseLimitMs = mAllowedTimePerPeriodMs[standbyBucket]; if (Flags.adjustQuotaDefaultConstants() && !isCompatOverridedForQuotaConstantAdjustment() && Flags.additionalQuotaForSystemInstaller() && standbyBucket == EXEMPTED_INDEX && mSystemInstallers.contains(userId, pkgName)) { Loading Loading @@ -1473,10 +1494,21 @@ public final class QuotaController extends StateController { } } void handleQuotaDefaultConstantsCompatChange() { synchronized (mLock) { final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); mQcConstants.adjustDefaultBucketWindowSizes(isCompatEnabled); mQcConstants.adjustDefaultEjLimits(isCompatEnabled); mQcConstants.mShouldReevaluateConstraints = true; onConstantsUpdatedLocked(); } } void processQuotaConstantsAdjustment() { if (Flags.adjustQuotaDefaultConstants()) { mQcConstants.adjustDefaultBucketWindowSizes(); mQcConstants.adjustDefaultEjLimits(); if (Flags.adjustQuotaDefaultConstants() && !isCompatOverridedForQuotaConstantAdjustment()) { mQcConstants.adjustDefaultBucketWindowSizes(false); mQcConstants.adjustDefaultEjLimits(false); } } Loading Loading @@ -1505,6 +1537,11 @@ public final class QuotaController extends StateController { } } private boolean isCompatOverridedForQuotaConstantAdjustment() { return mPlatformCompat.isChangeEnabledByPackageName( OVERRIDE_QUOTA_ADJUST_DEFAULT_CONSTANTS, "android", UserHandle.USER_SYSTEM); } private void incrementTimingSessionCountLocked(final int userId, @NonNull final String packageName) { final long now = sElapsedRealtimeClock.millis(); Loading Loading @@ -2689,7 +2726,8 @@ public final class QuotaController extends StateController { @VisibleForTesting int getProcessStateQuotaFreeThreshold(int uid) { if (Flags.enforceQuotaPolicyToFgsJobs() && !CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS, uid)) { && !mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS, uid)) { return ActivityManager.PROCESS_STATE_BOUND_TOP; } Loading Loading @@ -3596,14 +3634,28 @@ public final class QuotaController extends StateController { */ public long EJ_GRACE_PERIOD_TOP_APP_MS = DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS; void adjustDefaultBucketWindowSizes() { void adjustDefaultBucketWindowSizes(boolean useLegacyQuotaConstants) { if (useLegacyQuotaConstants) { ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS = DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS; ALLOWED_TIME_PER_PERIOD_ACTIVE_MS = DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS; ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS; WINDOW_SIZE_EXEMPTED_MS = DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS; WINDOW_SIZE_ACTIVE_MS = DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS; WINDOW_SIZE_WORKING_MS = DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS; WINDOW_SIZE_FREQUENT_MS = DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS; } else { ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS = Flags.tuneQuotaWindowDefaultParameters() ? DEFAULT_CURRENT_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS : DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS; ALLOWED_TIME_PER_PERIOD_ACTIVE_MS = Flags.tuneQuotaWindowDefaultParameters() ? DEFAULT_CURRENT_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS : DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS; ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS = Flags.tuneQuotaWindowDefaultParameters() ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS = Flags.tuneQuotaWindowDefaultParameters() ? DEFAULT_CURRENT_ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS : DEFAULT_ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS; Loading @@ -3615,6 +3667,7 @@ public final class QuotaController extends StateController { DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS; WINDOW_SIZE_WORKING_MS = DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS; WINDOW_SIZE_FREQUENT_MS = DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS; } mAllowedTimePerPeriodMs[EXEMPTED_INDEX] = Math.min(MAX_PERIOD_MS, Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS)); Loading @@ -3640,10 +3693,15 @@ public final class QuotaController extends StateController { ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS); } void adjustDefaultEjLimits() { EJ_LIMIT_WORKING_MS = DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS; EJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; EJ_REWARD_INTERACTION_MS = DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS; void adjustDefaultEjLimits(boolean useLegacyQuotaConstants) { EJ_LIMIT_WORKING_MS = useLegacyQuotaConstants ? DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS : DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS; EJ_TOP_APP_TIME_CHUNK_SIZE_MS = useLegacyQuotaConstants ? DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS : DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; EJ_REWARD_INTERACTION_MS = useLegacyQuotaConstants ? DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS : DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS; // The limit must be in the range [15 minutes, active limit]. mEJLimitsMs[WORKING_INDEX] = Math.max(15 * MINUTE_IN_MILLIS, Loading @@ -3668,6 +3726,8 @@ public final class QuotaController extends StateController { public void processConstantLocked(@NonNull DeviceConfig.Properties properties, @NonNull String key) { final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); switch (key) { case KEY_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS: case KEY_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS: Loading Loading @@ -3835,7 +3895,8 @@ public final class QuotaController extends StateController { case KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS: // We don't need to re-evaluate execution stats or constraint status for this. EJ_TOP_APP_TIME_CHUNK_SIZE_MS = properties.getLong(key, Flags.adjustQuotaDefaultConstants() properties.getLong(key, Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS : DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS); // Limit chunking to be in the range [1 millisecond, 15 minutes] per event. Loading Loading @@ -3873,7 +3934,8 @@ public final class QuotaController extends StateController { case KEY_EJ_REWARD_INTERACTION_MS: // We don't need to re-evaluate execution stats or constraint status for this. EJ_REWARD_INTERACTION_MS = properties.getLong(key, Flags.adjustQuotaDefaultConstants() properties.getLong(key, Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS : DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS); // Limit interaction reward to be in the range [5 seconds, 15 minutes] per Loading Loading @@ -3914,6 +3976,8 @@ public final class QuotaController extends StateController { } mExecutionPeriodConstantsUpdated = true; final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); // Query the values as an atomic set. final DeviceConfig.Properties properties = DeviceConfig.getProperties( DeviceConfig.NAMESPACE_JOB_SCHEDULER, Loading Loading @@ -3958,27 +4022,27 @@ public final class QuotaController extends StateController { MAX_EXECUTION_TIME_MS = properties.getLong(KEY_MAX_EXECUTION_TIME_MS, DEFAULT_MAX_EXECUTION_TIME_MS); WINDOW_SIZE_EXEMPTED_MS = properties.getLong(KEY_WINDOW_SIZE_EXEMPTED_MS, (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled && Flags.tuneQuotaWindowDefaultParameters()) ? DEFAULT_LATEST_WINDOW_SIZE_EXEMPTED_MS : (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_EXEMPTED_MS : DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS)); WINDOW_SIZE_ACTIVE_MS = properties.getLong(KEY_WINDOW_SIZE_ACTIVE_MS, (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled && Flags.tuneQuotaWindowDefaultParameters()) ? DEFAULT_LATEST_WINDOW_SIZE_ACTIVE_MS : (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS : DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS)); WINDOW_SIZE_WORKING_MS = properties.getLong(KEY_WINDOW_SIZE_WORKING_MS, Flags.adjustQuotaDefaultConstants() Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS : DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS); WINDOW_SIZE_FREQUENT_MS = properties.getLong(KEY_WINDOW_SIZE_FREQUENT_MS, Flags.adjustQuotaDefaultConstants() Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS : DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS); WINDOW_SIZE_RARE_MS = properties.getLong(KEY_WINDOW_SIZE_RARE_MS, Loading Loading @@ -4149,6 +4213,8 @@ public final class QuotaController extends StateController { } mEJLimitConstantsUpdated = true; final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); // Query the values as an atomic set. final DeviceConfig.Properties properties = DeviceConfig.getProperties( DeviceConfig.NAMESPACE_JOB_SCHEDULER, Loading @@ -4163,7 +4229,7 @@ public final class QuotaController extends StateController { EJ_LIMIT_ACTIVE_MS = properties.getLong( KEY_EJ_LIMIT_ACTIVE_MS, DEFAULT_EJ_LIMIT_ACTIVE_MS); EJ_LIMIT_WORKING_MS = properties.getLong( KEY_EJ_LIMIT_WORKING_MS, Flags.adjustQuotaDefaultConstants() KEY_EJ_LIMIT_WORKING_MS, Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS : DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS); EJ_LIMIT_FREQUENT_MS = properties.getLong( Loading services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java +18 −11 Original line number Diff line number Diff line Loading @@ -56,12 +56,12 @@ import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.IActivityManager; import android.app.UiModeManager; import android.app.compat.CompatChanges; import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobWorkItem; import android.app.usage.UsageStatsManagerInternal; import android.compat.testing.PlatformCompatChangeRule; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; Loading @@ -81,6 +81,7 @@ import android.os.BatteryManagerInternal.ChargingPolicyChangeListener; import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.WorkSource; import android.os.WorkSource.WorkChain; Loading @@ -98,6 +99,7 @@ import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.PowerAllowlistInternal; import com.android.server.SystemServiceManager; import com.android.server.compat.PlatformCompat; import com.android.server.job.controllers.ConnectivityController; import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.QuotaController; Loading @@ -106,14 +108,10 @@ import com.android.server.job.restrictions.ThermalStatusRestriction; import com.android.server.pm.UserManagerInternal; import com.android.server.usage.AppStandbyInternal; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.Mock; Loading Loading @@ -147,9 +145,6 @@ public class JobSchedulerServiceTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); private ChargingPolicyChangeListener mChargingPolicyChangeListener; private int mSourceUid; Loading @@ -166,8 +161,10 @@ public class JobSchedulerServiceTest { mMockingSession = mockitoSession() .initMocks(this) .strictness(Strictness.LENIENT) .mockStatic(CompatChanges.class) .mockStatic(LocalServices.class) .mockStatic(PermissionChecker.class) .mockStatic(ServiceManager.class) .startMocking(); // Called in JobSchedulerService constructor. Loading Loading @@ -230,6 +227,9 @@ public class JobSchedulerServiceTest { ArgumentCaptor<ChargingPolicyChangeListener> chargingPolicyChangeListenerCaptor = ArgumentCaptor.forClass(ChargingPolicyChangeListener.class); doReturn(mock(PlatformCompat.class)) .when(() -> ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mService = new TestJobSchedulerService(mContext); mService.waitOnAsyncLoadingForTesting(); Loading Loading @@ -1074,12 +1074,15 @@ public class JobSchedulerServiceTest { */ @Test @EnableFlags(FLAG_HANDLE_ABANDONED_JOBS) @DisableCompatChanges({JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS}) public void testGetRescheduleJobForFailure_abandonedJob() { final long nowElapsed = sElapsedRealtimeClock.millis(); final long initialBackoffMs = MINUTE_IN_MILLIS; mService.mConstants.SYSTEM_STOP_TO_FAILURE_RATIO = 3; // Mock the OVERRIDE_HANDLE_ABANDONED_JOBS compat change overrides. when(CompatChanges.isChangeEnabled( eq(JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS), anyInt())).thenReturn(false); JobStatus originalJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo() .setBackoffCriteria(initialBackoffMs, JobInfo.BACKOFF_POLICY_LINEAR)); Loading Loading @@ -1148,8 +1151,10 @@ public class JobSchedulerServiceTest { */ @Test @EnableFlags(FLAG_HANDLE_ABANDONED_JOBS) @DisableCompatChanges({JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS}) public void testGetRescheduleJobForFailure_EnableFlagDisableCompatCheckAggressiveBackoff() { // Mock the OVERRIDE_HANDLE_ABANDONED_JOBS compat change overrides. when(CompatChanges.isChangeEnabled( eq(JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS), anyInt())).thenReturn(false); assertFalse(mService.shouldUseAggressiveBackoff( mService.mConstants.ABANDONED_JOB_TIMEOUTS_BEFORE_AGGRESSIVE_BACKOFF - 1, mSourceUid)); Loading @@ -1167,8 +1172,10 @@ public class JobSchedulerServiceTest { */ @Test @EnableFlags(FLAG_HANDLE_ABANDONED_JOBS) @EnableCompatChanges({JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS}) public void testGetRescheduleJobForFailure_EnableFlagEnableCompatCheckAggressiveBackoff() { // Mock the OVERRIDE_HANDLE_ABANDONED_JOBS compat change overrides. when(CompatChanges.isChangeEnabled( eq(JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS), anyInt())).thenReturn(true); assertFalse(mService.shouldUseAggressiveBackoff( mService.mConstants.ABANDONED_JOB_TIMEOUTS_BEFORE_AGGRESSIVE_BACKOFF - 1, mSourceUid)); Loading services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java +14 −4 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.os.BatteryManagerInternal; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; Loading @@ -93,6 +94,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.PowerAllowlistInternal; import com.android.server.compat.PlatformCompat; import com.android.server.job.Flags; import com.android.server.job.JobSchedulerInternal; import com.android.server.job.JobSchedulerService; Loading @@ -104,8 +106,6 @@ import com.android.server.job.controllers.QuotaController.TimedEvent; import com.android.server.job.controllers.QuotaController.TimingSession; import com.android.server.usage.AppStandbyInternal; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; import org.junit.After; import org.junit.Before; import org.junit.Rule; Loading Loading @@ -168,6 +168,8 @@ public class QuotaControllerTest { private PowerAllowlistInternal mPowerAllowlistInternal; @Mock private UsageStatsManagerInternal mUsageStatsManager; @Mock private PlatformCompat mPlatformCompat; @Rule public final CheckFlagsRule mCheckFlagsRule = Loading @@ -182,6 +184,7 @@ public class QuotaControllerTest { .strictness(Strictness.LENIENT) .spyStatic(DeviceConfig.class) .mockStatic(LocalServices.class) .mockStatic(ServiceManager.class) .startMocking(); // Called in StateController constructor. Loading @@ -198,6 +201,7 @@ public class QuotaControllerTest { } when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); when(mContext.getSystemService(AlarmManager.class)).thenReturn(mAlarmManager); doReturn(mActivityMangerInternal) .when(() -> LocalServices.getService(ActivityManagerInternal.class)); doReturn(mock(AppStandbyInternal.class)) Loading Loading @@ -253,6 +257,8 @@ public class QuotaControllerTest { ArgumentCaptor.forClass(PowerAllowlistInternal.TempAllowlistChangeListener.class); ArgumentCaptor<UsageStatsManagerInternal.UsageEventListener> ueListenerCaptor = ArgumentCaptor.forClass(UsageStatsManagerInternal.UsageEventListener.class); doReturn(mPlatformCompat) .when(() -> ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mQuotaController = new QuotaController(mJobSchedulerService, mock(BackgroundJobsController.class), mock(ConnectivityController.class)); Loading Loading @@ -5591,13 +5597,17 @@ public class QuotaControllerTest { } @Test @EnableCompatChanges({QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS}) @RequiresFlagsEnabled({Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS, Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_FGS_JOBS}) public void testTracking_OutOfQuota_ForegroundAndBackground_CompactChangeOverrides() { setDischarging(); // Mock the OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS compat change overrides. doReturn(true).when(mPlatformCompat).isChangeEnabledByUid( eq(QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS), anyInt()); doReturn(true).when(mPlatformCompat).isChangeEnabledByUid( eq(QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS), anyInt()); JobStatus jobBg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 1); JobStatus jobTop = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 2); trackJobs(jobBg, jobTop); Loading Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +109 −43 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.UidObserver; import android.app.compat.CompatChanges; import android.app.job.JobInfo; import android.app.usage.UsageEvents; import android.app.usage.UsageStatsManagerInternal; Loading @@ -54,6 +53,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.Trace; import android.os.UserHandle; import android.provider.DeviceConfig; Loading @@ -74,6 +74,7 @@ import com.android.internal.util.ArrayUtils; import com.android.server.AppSchedulingModuleThread; import com.android.server.LocalServices; import com.android.server.PowerAllowlistInternal; import com.android.server.compat.PlatformCompat; import com.android.server.job.ConstantsProto; import com.android.server.job.Flags; import com.android.server.job.JobSchedulerService; Loading Loading @@ -157,6 +158,15 @@ public final class QuotaController extends StateController { @Overridable // The change can be overridden in user build. static final long OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS = 374323858L; /** * When enabled this change id overrides the default quota parameters adjustment. */ @VisibleForTesting @ChangeId @Disabled // Disabled by default @Overridable // The change can be overridden in user build. static final long OVERRIDE_QUOTA_ADJUST_DEFAULT_CONSTANTS = 378129159L; @VisibleForTesting static class ExecutionStats { /** Loading Loading @@ -536,6 +546,8 @@ public final class QuotaController extends StateController { */ private final SparseSetArray<String> mSystemInstallers = new SparseSetArray<>(); private final PlatformCompat mPlatformCompat; /** An app has reached its quota. The message should contain a {@link UserPackage} object. */ @VisibleForTesting static final int MSG_REACHED_TIME_QUOTA = 0; Loading Loading @@ -587,6 +599,13 @@ public final class QuotaController extends StateController { PowerAllowlistInternal pai = LocalServices.getService(PowerAllowlistInternal.class); pai.registerTempAllowlistChangeListener(new TempAllowlistTracker()); mPlatformCompat = (PlatformCompat) ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); if (Flags.adjustQuotaDefaultConstants()) { mPlatformCompat.registerListener(OVERRIDE_QUOTA_ADJUST_DEFAULT_CONSTANTS, (packageName) -> handleQuotaDefaultConstantsCompatChange()); } try { ActivityManager.getService().registerUidObserver(new QcUidObserver(), ActivityManager.UID_OBSERVER_PROCSTATE, Loading Loading @@ -651,8 +670,9 @@ public final class QuotaController extends StateController { final int uid = jobStatus.getSourceUid(); if ((!Flags.enforceQuotaPolicyToTopStartedJobs() || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, uid)) && mTopAppCache.get(uid)) { || mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, uid)) && mTopAppCache.get(uid)) { if (DEBUG) { Slog.d(TAG, jobStatus.toShortString() + " is top started job"); } Loading Loading @@ -690,8 +710,8 @@ public final class QuotaController extends StateController { } } if (!Flags.enforceQuotaPolicyToTopStartedJobs() || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { || mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { mTopStartedJobs.remove(jobStatus); } } Loading Loading @@ -805,8 +825,8 @@ public final class QuotaController extends StateController { /** @return true if the job was started while the app was in the TOP state. */ private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) { if (!Flags.enforceQuotaPolicyToTopStartedJobs() || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { || mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, jobStatus.getSourceUid())) { return mTopStartedJobs.contains(jobStatus); } Loading Loading @@ -1102,6 +1122,7 @@ public final class QuotaController extends StateController { final int standbyBucket) { final long baseLimitMs = mAllowedTimePerPeriodMs[standbyBucket]; if (Flags.adjustQuotaDefaultConstants() && !isCompatOverridedForQuotaConstantAdjustment() && Flags.additionalQuotaForSystemInstaller() && standbyBucket == EXEMPTED_INDEX && mSystemInstallers.contains(userId, pkgName)) { Loading Loading @@ -1473,10 +1494,21 @@ public final class QuotaController extends StateController { } } void handleQuotaDefaultConstantsCompatChange() { synchronized (mLock) { final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); mQcConstants.adjustDefaultBucketWindowSizes(isCompatEnabled); mQcConstants.adjustDefaultEjLimits(isCompatEnabled); mQcConstants.mShouldReevaluateConstraints = true; onConstantsUpdatedLocked(); } } void processQuotaConstantsAdjustment() { if (Flags.adjustQuotaDefaultConstants()) { mQcConstants.adjustDefaultBucketWindowSizes(); mQcConstants.adjustDefaultEjLimits(); if (Flags.adjustQuotaDefaultConstants() && !isCompatOverridedForQuotaConstantAdjustment()) { mQcConstants.adjustDefaultBucketWindowSizes(false); mQcConstants.adjustDefaultEjLimits(false); } } Loading Loading @@ -1505,6 +1537,11 @@ public final class QuotaController extends StateController { } } private boolean isCompatOverridedForQuotaConstantAdjustment() { return mPlatformCompat.isChangeEnabledByPackageName( OVERRIDE_QUOTA_ADJUST_DEFAULT_CONSTANTS, "android", UserHandle.USER_SYSTEM); } private void incrementTimingSessionCountLocked(final int userId, @NonNull final String packageName) { final long now = sElapsedRealtimeClock.millis(); Loading Loading @@ -2689,7 +2726,8 @@ public final class QuotaController extends StateController { @VisibleForTesting int getProcessStateQuotaFreeThreshold(int uid) { if (Flags.enforceQuotaPolicyToFgsJobs() && !CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS, uid)) { && !mPlatformCompat.isChangeEnabledByUid( OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS, uid)) { return ActivityManager.PROCESS_STATE_BOUND_TOP; } Loading Loading @@ -3596,14 +3634,28 @@ public final class QuotaController extends StateController { */ public long EJ_GRACE_PERIOD_TOP_APP_MS = DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS; void adjustDefaultBucketWindowSizes() { void adjustDefaultBucketWindowSizes(boolean useLegacyQuotaConstants) { if (useLegacyQuotaConstants) { ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS = DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS; ALLOWED_TIME_PER_PERIOD_ACTIVE_MS = DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS; ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS; WINDOW_SIZE_EXEMPTED_MS = DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS; WINDOW_SIZE_ACTIVE_MS = DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS; WINDOW_SIZE_WORKING_MS = DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS; WINDOW_SIZE_FREQUENT_MS = DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS; } else { ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS = Flags.tuneQuotaWindowDefaultParameters() ? DEFAULT_CURRENT_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS : DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS; ALLOWED_TIME_PER_PERIOD_ACTIVE_MS = Flags.tuneQuotaWindowDefaultParameters() ? DEFAULT_CURRENT_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS : DEFAULT_LEGACY_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS; ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS = Flags.tuneQuotaWindowDefaultParameters() ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS = Flags.tuneQuotaWindowDefaultParameters() ? DEFAULT_CURRENT_ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS : DEFAULT_ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS; Loading @@ -3615,6 +3667,7 @@ public final class QuotaController extends StateController { DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS; WINDOW_SIZE_WORKING_MS = DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS; WINDOW_SIZE_FREQUENT_MS = DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS; } mAllowedTimePerPeriodMs[EXEMPTED_INDEX] = Math.min(MAX_PERIOD_MS, Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS)); Loading @@ -3640,10 +3693,15 @@ public final class QuotaController extends StateController { ALLOWED_TIME_PER_PERIOD_ADDITION_INSTALLER_MS); } void adjustDefaultEjLimits() { EJ_LIMIT_WORKING_MS = DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS; EJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; EJ_REWARD_INTERACTION_MS = DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS; void adjustDefaultEjLimits(boolean useLegacyQuotaConstants) { EJ_LIMIT_WORKING_MS = useLegacyQuotaConstants ? DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS : DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS; EJ_TOP_APP_TIME_CHUNK_SIZE_MS = useLegacyQuotaConstants ? DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS : DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; EJ_REWARD_INTERACTION_MS = useLegacyQuotaConstants ? DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS : DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS; // The limit must be in the range [15 minutes, active limit]. mEJLimitsMs[WORKING_INDEX] = Math.max(15 * MINUTE_IN_MILLIS, Loading @@ -3668,6 +3726,8 @@ public final class QuotaController extends StateController { public void processConstantLocked(@NonNull DeviceConfig.Properties properties, @NonNull String key) { final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); switch (key) { case KEY_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS: case KEY_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS: Loading Loading @@ -3835,7 +3895,8 @@ public final class QuotaController extends StateController { case KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS: // We don't need to re-evaluate execution stats or constraint status for this. EJ_TOP_APP_TIME_CHUNK_SIZE_MS = properties.getLong(key, Flags.adjustQuotaDefaultConstants() properties.getLong(key, Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS : DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS); // Limit chunking to be in the range [1 millisecond, 15 minutes] per event. Loading Loading @@ -3873,7 +3934,8 @@ public final class QuotaController extends StateController { case KEY_EJ_REWARD_INTERACTION_MS: // We don't need to re-evaluate execution stats or constraint status for this. EJ_REWARD_INTERACTION_MS = properties.getLong(key, Flags.adjustQuotaDefaultConstants() properties.getLong(key, Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS : DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS); // Limit interaction reward to be in the range [5 seconds, 15 minutes] per Loading Loading @@ -3914,6 +3976,8 @@ public final class QuotaController extends StateController { } mExecutionPeriodConstantsUpdated = true; final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); // Query the values as an atomic set. final DeviceConfig.Properties properties = DeviceConfig.getProperties( DeviceConfig.NAMESPACE_JOB_SCHEDULER, Loading Loading @@ -3958,27 +4022,27 @@ public final class QuotaController extends StateController { MAX_EXECUTION_TIME_MS = properties.getLong(KEY_MAX_EXECUTION_TIME_MS, DEFAULT_MAX_EXECUTION_TIME_MS); WINDOW_SIZE_EXEMPTED_MS = properties.getLong(KEY_WINDOW_SIZE_EXEMPTED_MS, (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled && Flags.tuneQuotaWindowDefaultParameters()) ? DEFAULT_LATEST_WINDOW_SIZE_EXEMPTED_MS : (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_EXEMPTED_MS : DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS)); WINDOW_SIZE_ACTIVE_MS = properties.getLong(KEY_WINDOW_SIZE_ACTIVE_MS, (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled && Flags.tuneQuotaWindowDefaultParameters()) ? DEFAULT_LATEST_WINDOW_SIZE_ACTIVE_MS : (Flags.adjustQuotaDefaultConstants() (Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS : DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS)); WINDOW_SIZE_WORKING_MS = properties.getLong(KEY_WINDOW_SIZE_WORKING_MS, Flags.adjustQuotaDefaultConstants() Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS : DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS); WINDOW_SIZE_FREQUENT_MS = properties.getLong(KEY_WINDOW_SIZE_FREQUENT_MS, Flags.adjustQuotaDefaultConstants() Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS : DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS); WINDOW_SIZE_RARE_MS = properties.getLong(KEY_WINDOW_SIZE_RARE_MS, Loading Loading @@ -4149,6 +4213,8 @@ public final class QuotaController extends StateController { } mEJLimitConstantsUpdated = true; final boolean isCompatEnabled = isCompatOverridedForQuotaConstantAdjustment(); // Query the values as an atomic set. final DeviceConfig.Properties properties = DeviceConfig.getProperties( DeviceConfig.NAMESPACE_JOB_SCHEDULER, Loading @@ -4163,7 +4229,7 @@ public final class QuotaController extends StateController { EJ_LIMIT_ACTIVE_MS = properties.getLong( KEY_EJ_LIMIT_ACTIVE_MS, DEFAULT_EJ_LIMIT_ACTIVE_MS); EJ_LIMIT_WORKING_MS = properties.getLong( KEY_EJ_LIMIT_WORKING_MS, Flags.adjustQuotaDefaultConstants() KEY_EJ_LIMIT_WORKING_MS, Flags.adjustQuotaDefaultConstants() && !isCompatEnabled ? DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS : DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS); EJ_LIMIT_FREQUENT_MS = properties.getLong( Loading
services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java +18 −11 Original line number Diff line number Diff line Loading @@ -56,12 +56,12 @@ import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.IActivityManager; import android.app.UiModeManager; import android.app.compat.CompatChanges; import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobWorkItem; import android.app.usage.UsageStatsManagerInternal; import android.compat.testing.PlatformCompatChangeRule; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; Loading @@ -81,6 +81,7 @@ import android.os.BatteryManagerInternal.ChargingPolicyChangeListener; import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.WorkSource; import android.os.WorkSource.WorkChain; Loading @@ -98,6 +99,7 @@ import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.PowerAllowlistInternal; import com.android.server.SystemServiceManager; import com.android.server.compat.PlatformCompat; import com.android.server.job.controllers.ConnectivityController; import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.QuotaController; Loading @@ -106,14 +108,10 @@ import com.android.server.job.restrictions.ThermalStatusRestriction; import com.android.server.pm.UserManagerInternal; import com.android.server.usage.AppStandbyInternal; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.Mock; Loading Loading @@ -147,9 +145,6 @@ public class JobSchedulerServiceTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); private ChargingPolicyChangeListener mChargingPolicyChangeListener; private int mSourceUid; Loading @@ -166,8 +161,10 @@ public class JobSchedulerServiceTest { mMockingSession = mockitoSession() .initMocks(this) .strictness(Strictness.LENIENT) .mockStatic(CompatChanges.class) .mockStatic(LocalServices.class) .mockStatic(PermissionChecker.class) .mockStatic(ServiceManager.class) .startMocking(); // Called in JobSchedulerService constructor. Loading Loading @@ -230,6 +227,9 @@ public class JobSchedulerServiceTest { ArgumentCaptor<ChargingPolicyChangeListener> chargingPolicyChangeListenerCaptor = ArgumentCaptor.forClass(ChargingPolicyChangeListener.class); doReturn(mock(PlatformCompat.class)) .when(() -> ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mService = new TestJobSchedulerService(mContext); mService.waitOnAsyncLoadingForTesting(); Loading Loading @@ -1074,12 +1074,15 @@ public class JobSchedulerServiceTest { */ @Test @EnableFlags(FLAG_HANDLE_ABANDONED_JOBS) @DisableCompatChanges({JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS}) public void testGetRescheduleJobForFailure_abandonedJob() { final long nowElapsed = sElapsedRealtimeClock.millis(); final long initialBackoffMs = MINUTE_IN_MILLIS; mService.mConstants.SYSTEM_STOP_TO_FAILURE_RATIO = 3; // Mock the OVERRIDE_HANDLE_ABANDONED_JOBS compat change overrides. when(CompatChanges.isChangeEnabled( eq(JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS), anyInt())).thenReturn(false); JobStatus originalJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo() .setBackoffCriteria(initialBackoffMs, JobInfo.BACKOFF_POLICY_LINEAR)); Loading Loading @@ -1148,8 +1151,10 @@ public class JobSchedulerServiceTest { */ @Test @EnableFlags(FLAG_HANDLE_ABANDONED_JOBS) @DisableCompatChanges({JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS}) public void testGetRescheduleJobForFailure_EnableFlagDisableCompatCheckAggressiveBackoff() { // Mock the OVERRIDE_HANDLE_ABANDONED_JOBS compat change overrides. when(CompatChanges.isChangeEnabled( eq(JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS), anyInt())).thenReturn(false); assertFalse(mService.shouldUseAggressiveBackoff( mService.mConstants.ABANDONED_JOB_TIMEOUTS_BEFORE_AGGRESSIVE_BACKOFF - 1, mSourceUid)); Loading @@ -1167,8 +1172,10 @@ public class JobSchedulerServiceTest { */ @Test @EnableFlags(FLAG_HANDLE_ABANDONED_JOBS) @EnableCompatChanges({JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS}) public void testGetRescheduleJobForFailure_EnableFlagEnableCompatCheckAggressiveBackoff() { // Mock the OVERRIDE_HANDLE_ABANDONED_JOBS compat change overrides. when(CompatChanges.isChangeEnabled( eq(JobParameters.OVERRIDE_HANDLE_ABANDONED_JOBS), anyInt())).thenReturn(true); assertFalse(mService.shouldUseAggressiveBackoff( mService.mConstants.ABANDONED_JOB_TIMEOUTS_BEFORE_AGGRESSIVE_BACKOFF - 1, mSourceUid)); Loading
services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java +14 −4 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.os.BatteryManagerInternal; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; Loading @@ -93,6 +94,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.PowerAllowlistInternal; import com.android.server.compat.PlatformCompat; import com.android.server.job.Flags; import com.android.server.job.JobSchedulerInternal; import com.android.server.job.JobSchedulerService; Loading @@ -104,8 +106,6 @@ import com.android.server.job.controllers.QuotaController.TimedEvent; import com.android.server.job.controllers.QuotaController.TimingSession; import com.android.server.usage.AppStandbyInternal; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; import org.junit.After; import org.junit.Before; import org.junit.Rule; Loading Loading @@ -168,6 +168,8 @@ public class QuotaControllerTest { private PowerAllowlistInternal mPowerAllowlistInternal; @Mock private UsageStatsManagerInternal mUsageStatsManager; @Mock private PlatformCompat mPlatformCompat; @Rule public final CheckFlagsRule mCheckFlagsRule = Loading @@ -182,6 +184,7 @@ public class QuotaControllerTest { .strictness(Strictness.LENIENT) .spyStatic(DeviceConfig.class) .mockStatic(LocalServices.class) .mockStatic(ServiceManager.class) .startMocking(); // Called in StateController constructor. Loading @@ -198,6 +201,7 @@ public class QuotaControllerTest { } when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); when(mContext.getSystemService(AlarmManager.class)).thenReturn(mAlarmManager); doReturn(mActivityMangerInternal) .when(() -> LocalServices.getService(ActivityManagerInternal.class)); doReturn(mock(AppStandbyInternal.class)) Loading Loading @@ -253,6 +257,8 @@ public class QuotaControllerTest { ArgumentCaptor.forClass(PowerAllowlistInternal.TempAllowlistChangeListener.class); ArgumentCaptor<UsageStatsManagerInternal.UsageEventListener> ueListenerCaptor = ArgumentCaptor.forClass(UsageStatsManagerInternal.UsageEventListener.class); doReturn(mPlatformCompat) .when(() -> ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mQuotaController = new QuotaController(mJobSchedulerService, mock(BackgroundJobsController.class), mock(ConnectivityController.class)); Loading Loading @@ -5591,13 +5597,17 @@ public class QuotaControllerTest { } @Test @EnableCompatChanges({QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS, QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS}) @RequiresFlagsEnabled({Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS, Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_FGS_JOBS}) public void testTracking_OutOfQuota_ForegroundAndBackground_CompactChangeOverrides() { setDischarging(); // Mock the OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS compat change overrides. doReturn(true).when(mPlatformCompat).isChangeEnabledByUid( eq(QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS), anyInt()); doReturn(true).when(mPlatformCompat).isChangeEnabledByUid( eq(QuotaController.OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS), anyInt()); JobStatus jobBg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 1); JobStatus jobTop = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 2); trackJobs(jobBg, jobTop); Loading