Merge "Migrate QuotaController to DeviceConfig."
This commit is contained in:
committed by
Android (Google) Code Review
commit
27cec559d3
@@ -339,6 +339,11 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
public void onPropertiesChanged(DeviceConfig.Properties properties) {
|
||||
boolean apiQuotaScheduleUpdated = false;
|
||||
boolean concurrencyUpdated = false;
|
||||
for (int controller = 0; controller < mControllers.size(); controller++) {
|
||||
final StateController sc = mControllers.get(controller);
|
||||
sc.prepareForUpdatedConstantsLocked();
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
for (String name : properties.getKeyset()) {
|
||||
if (name == null) {
|
||||
@@ -384,6 +389,11 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
&& !concurrencyUpdated) {
|
||||
mConstants.updateConcurrencyConstantsLocked();
|
||||
concurrencyUpdated = true;
|
||||
} else {
|
||||
for (int ctrlr = 0; ctrlr < mControllers.size(); ctrlr++) {
|
||||
final StateController sc = mControllers.get(ctrlr);
|
||||
sc.processConstantLocked(properties, name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1388,6 +1388,11 @@ public final class JobStatus {
|
||||
}
|
||||
if (isReady()) {
|
||||
sb.append(" READY");
|
||||
} else {
|
||||
sb.append(" satisfied:0x").append(Integer.toHexString(satisfiedConstraints));
|
||||
sb.append(" unsatisfied:0x").append(Integer.toHexString(
|
||||
(satisfiedConstraints & mRequiredConstraintsOfInterest)
|
||||
^ mRequiredConstraintsOfInterest));
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
|
||||
@@ -37,12 +37,9 @@ import android.app.AlarmManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.IUidObserver;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryManagerInternal;
|
||||
import android.os.Handler;
|
||||
@@ -50,10 +47,9 @@ import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.KeyValueListParser;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
@@ -494,7 +490,7 @@ public final class QuotaController extends StateController {
|
||||
mChargeTracker.startTracking();
|
||||
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
|
||||
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
|
||||
mQcConstants = new QcConstants(mHandler);
|
||||
mQcConstants = new QcConstants();
|
||||
|
||||
final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
mContext.registerReceiverAsUser(mPackageAddedReceiver, UserHandle.ALL, filter, null, null);
|
||||
@@ -512,11 +508,6 @@ public final class QuotaController extends StateController {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSystemServicesReady() {
|
||||
mQcConstants.start(mContext.getContentResolver());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
|
||||
final int userId = jobStatus.getSourceUserId();
|
||||
@@ -2028,38 +2019,109 @@ public final class QuotaController extends StateController {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class QcConstants extends ContentObserver {
|
||||
private ContentResolver mResolver;
|
||||
private final KeyValueListParser mParser = new KeyValueListParser(',');
|
||||
@Override
|
||||
public void prepareForUpdatedConstantsLocked() {
|
||||
mQcConstants.mShouldReevaluateConstraints = false;
|
||||
mQcConstants.mRateLimitingConstantsUpdated = false;
|
||||
mQcConstants.mExecutionPeriodConstantsUpdated = false;
|
||||
}
|
||||
|
||||
private static final String KEY_ALLOWED_TIME_PER_PERIOD_MS = "allowed_time_per_period_ms";
|
||||
private static final String KEY_IN_QUOTA_BUFFER_MS = "in_quota_buffer_ms";
|
||||
private static final String KEY_WINDOW_SIZE_ACTIVE_MS = "window_size_active_ms";
|
||||
private static final String KEY_WINDOW_SIZE_WORKING_MS = "window_size_working_ms";
|
||||
private static final String KEY_WINDOW_SIZE_FREQUENT_MS = "window_size_frequent_ms";
|
||||
private static final String KEY_WINDOW_SIZE_RARE_MS = "window_size_rare_ms";
|
||||
private static final String KEY_WINDOW_SIZE_RESTRICTED_MS = "window_size_restricted_ms";
|
||||
private static final String KEY_MAX_EXECUTION_TIME_MS = "max_execution_time_ms";
|
||||
private static final String KEY_MAX_JOB_COUNT_ACTIVE = "max_job_count_active";
|
||||
private static final String KEY_MAX_JOB_COUNT_WORKING = "max_job_count_working";
|
||||
private static final String KEY_MAX_JOB_COUNT_FREQUENT = "max_job_count_frequent";
|
||||
private static final String KEY_MAX_JOB_COUNT_RARE = "max_job_count_rare";
|
||||
private static final String KEY_MAX_JOB_COUNT_RESTRICTED = "max_job_count_restricted";
|
||||
private static final String KEY_RATE_LIMITING_WINDOW_MS = "rate_limiting_window_ms";
|
||||
private static final String KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
|
||||
"max_job_count_per_rate_limiting_window";
|
||||
private static final String KEY_MAX_SESSION_COUNT_ACTIVE = "max_session_count_active";
|
||||
private static final String KEY_MAX_SESSION_COUNT_WORKING = "max_session_count_working";
|
||||
private static final String KEY_MAX_SESSION_COUNT_FREQUENT = "max_session_count_frequent";
|
||||
private static final String KEY_MAX_SESSION_COUNT_RARE = "max_session_count_rare";
|
||||
private static final String KEY_MAX_SESSION_COUNT_RESTRICTED =
|
||||
"max_session_count_restricted";
|
||||
private static final String KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
|
||||
"max_session_count_per_rate_limiting_window";
|
||||
private static final String KEY_TIMING_SESSION_COALESCING_DURATION_MS =
|
||||
"timing_session_coalescing_duration_ms";
|
||||
private static final String KEY_MIN_QUOTA_CHECK_DELAY_MS = "min_quota_check_delay_ms";
|
||||
@Override
|
||||
public void processConstantLocked(DeviceConfig.Properties properties, String key) {
|
||||
mQcConstants.processConstantLocked(properties, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConstantsUpdatedLocked() {
|
||||
if (mQcConstants.mShouldReevaluateConstraints) {
|
||||
// Update job bookkeeping out of band.
|
||||
JobSchedulerBackgroundThread.getHandler().post(() -> {
|
||||
synchronized (mLock) {
|
||||
invalidateAllExecutionStatsLocked();
|
||||
maybeUpdateAllConstraintsLocked();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class QcConstants {
|
||||
private boolean mShouldReevaluateConstraints = false;
|
||||
private boolean mRateLimitingConstantsUpdated = false;
|
||||
private boolean mExecutionPeriodConstantsUpdated = false;
|
||||
|
||||
/** Prefix to use with all constant keys in order to "sub-namespace" the keys. */
|
||||
private static final String QC_CONSTANT_PREFIX = "qc_";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_ALLOWED_TIME_PER_PERIOD_MS =
|
||||
QC_CONSTANT_PREFIX + "allowed_time_per_period_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_IN_QUOTA_BUFFER_MS =
|
||||
QC_CONSTANT_PREFIX + "in_quota_buffer_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WINDOW_SIZE_ACTIVE_MS =
|
||||
QC_CONSTANT_PREFIX + "window_size_active_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WINDOW_SIZE_WORKING_MS =
|
||||
QC_CONSTANT_PREFIX + "window_size_working_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WINDOW_SIZE_FREQUENT_MS =
|
||||
QC_CONSTANT_PREFIX + "window_size_frequent_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WINDOW_SIZE_RARE_MS =
|
||||
QC_CONSTANT_PREFIX + "window_size_rare_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WINDOW_SIZE_RESTRICTED_MS =
|
||||
QC_CONSTANT_PREFIX + "window_size_restricted_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_EXECUTION_TIME_MS =
|
||||
QC_CONSTANT_PREFIX + "max_execution_time_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_JOB_COUNT_ACTIVE =
|
||||
QC_CONSTANT_PREFIX + "max_job_count_active";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_JOB_COUNT_WORKING =
|
||||
QC_CONSTANT_PREFIX + "max_job_count_working";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_JOB_COUNT_FREQUENT =
|
||||
QC_CONSTANT_PREFIX + "max_job_count_frequent";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_JOB_COUNT_RARE =
|
||||
QC_CONSTANT_PREFIX + "max_job_count_rare";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_JOB_COUNT_RESTRICTED =
|
||||
QC_CONSTANT_PREFIX + "max_job_count_restricted";
|
||||
@VisibleForTesting
|
||||
static final String KEY_RATE_LIMITING_WINDOW_MS =
|
||||
QC_CONSTANT_PREFIX + "rate_limiting_window_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
|
||||
QC_CONSTANT_PREFIX + "max_job_count_per_rate_limiting_window";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_SESSION_COUNT_ACTIVE =
|
||||
QC_CONSTANT_PREFIX + "max_session_count_active";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_SESSION_COUNT_WORKING =
|
||||
QC_CONSTANT_PREFIX + "max_session_count_working";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_SESSION_COUNT_FREQUENT =
|
||||
QC_CONSTANT_PREFIX + "max_session_count_frequent";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_SESSION_COUNT_RARE =
|
||||
QC_CONSTANT_PREFIX + "max_session_count_rare";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_SESSION_COUNT_RESTRICTED =
|
||||
QC_CONSTANT_PREFIX + "max_session_count_restricted";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
|
||||
QC_CONSTANT_PREFIX + "max_session_count_per_rate_limiting_window";
|
||||
@VisibleForTesting
|
||||
static final String KEY_TIMING_SESSION_COALESCING_DURATION_MS =
|
||||
QC_CONSTANT_PREFIX + "timing_session_coalescing_duration_ms";
|
||||
@VisibleForTesting
|
||||
static final String KEY_MIN_QUOTA_CHECK_DELAY_MS =
|
||||
QC_CONSTANT_PREFIX + "min_quota_check_delay_ms";
|
||||
|
||||
private static final long DEFAULT_ALLOWED_TIME_PER_PERIOD_MS =
|
||||
10 * 60 * 1000L; // 10 minutes
|
||||
@@ -2260,238 +2322,273 @@ public final class QuotaController extends StateController {
|
||||
/** The minimum value that {@link #RATE_LIMITING_WINDOW_MS} can have. */
|
||||
private static final long MIN_RATE_LIMITING_WINDOW_MS = 30 * SECOND_IN_MILLIS;
|
||||
|
||||
QcConstants(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
|
||||
@NonNull String key) {
|
||||
switch (key) {
|
||||
case KEY_ALLOWED_TIME_PER_PERIOD_MS:
|
||||
case KEY_IN_QUOTA_BUFFER_MS:
|
||||
case KEY_MAX_EXECUTION_TIME_MS:
|
||||
case KEY_WINDOW_SIZE_ACTIVE_MS:
|
||||
case KEY_WINDOW_SIZE_WORKING_MS:
|
||||
case KEY_WINDOW_SIZE_FREQUENT_MS:
|
||||
case KEY_WINDOW_SIZE_RARE_MS:
|
||||
case KEY_WINDOW_SIZE_RESTRICTED_MS:
|
||||
updateExecutionPeriodConstantsLocked();
|
||||
break;
|
||||
|
||||
private void start(ContentResolver resolver) {
|
||||
mResolver = resolver;
|
||||
mResolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS), false, this);
|
||||
onChange(true, null);
|
||||
}
|
||||
case KEY_RATE_LIMITING_WINDOW_MS:
|
||||
case KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW:
|
||||
case KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW:
|
||||
updateRateLimitingConstantsLocked();
|
||||
break;
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
final String constants = Settings.Global.getString(
|
||||
mResolver, Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS);
|
||||
|
||||
try {
|
||||
mParser.setString(constants);
|
||||
} catch (Exception e) {
|
||||
// Failed to parse the settings string, log this and move on with defaults.
|
||||
Slog.e(TAG, "Bad jobscheduler quota controller settings", e);
|
||||
case KEY_MAX_JOB_COUNT_ACTIVE:
|
||||
MAX_JOB_COUNT_ACTIVE = properties.getInt(key, DEFAULT_MAX_JOB_COUNT_ACTIVE);
|
||||
int newActiveMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_ACTIVE);
|
||||
if (mMaxBucketJobCounts[ACTIVE_INDEX] != newActiveMaxJobCount) {
|
||||
mMaxBucketJobCounts[ACTIVE_INDEX] = newActiveMaxJobCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_JOB_COUNT_WORKING:
|
||||
MAX_JOB_COUNT_WORKING = properties.getInt(key, DEFAULT_MAX_JOB_COUNT_WORKING);
|
||||
int newWorkingMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT,
|
||||
MAX_JOB_COUNT_WORKING);
|
||||
if (mMaxBucketJobCounts[WORKING_INDEX] != newWorkingMaxJobCount) {
|
||||
mMaxBucketJobCounts[WORKING_INDEX] = newWorkingMaxJobCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_JOB_COUNT_FREQUENT:
|
||||
MAX_JOB_COUNT_FREQUENT = properties.getInt(key, DEFAULT_MAX_JOB_COUNT_FREQUENT);
|
||||
int newFrequentMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT,
|
||||
MAX_JOB_COUNT_FREQUENT);
|
||||
if (mMaxBucketJobCounts[FREQUENT_INDEX] != newFrequentMaxJobCount) {
|
||||
mMaxBucketJobCounts[FREQUENT_INDEX] = newFrequentMaxJobCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_JOB_COUNT_RARE:
|
||||
MAX_JOB_COUNT_RARE = properties.getInt(key, DEFAULT_MAX_JOB_COUNT_RARE);
|
||||
int newRareMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RARE);
|
||||
if (mMaxBucketJobCounts[RARE_INDEX] != newRareMaxJobCount) {
|
||||
mMaxBucketJobCounts[RARE_INDEX] = newRareMaxJobCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_JOB_COUNT_RESTRICTED:
|
||||
MAX_JOB_COUNT_RESTRICTED =
|
||||
properties.getInt(key, DEFAULT_MAX_JOB_COUNT_RESTRICTED);
|
||||
int newRestrictedMaxJobCount =
|
||||
Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RESTRICTED);
|
||||
if (mMaxBucketJobCounts[RESTRICTED_INDEX] != newRestrictedMaxJobCount) {
|
||||
mMaxBucketJobCounts[RESTRICTED_INDEX] = newRestrictedMaxJobCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_SESSION_COUNT_ACTIVE:
|
||||
MAX_SESSION_COUNT_ACTIVE =
|
||||
properties.getInt(key, DEFAULT_MAX_SESSION_COUNT_ACTIVE);
|
||||
int newActiveMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_ACTIVE);
|
||||
if (mMaxBucketSessionCounts[ACTIVE_INDEX] != newActiveMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[ACTIVE_INDEX] = newActiveMaxSessionCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_SESSION_COUNT_WORKING:
|
||||
MAX_SESSION_COUNT_WORKING =
|
||||
properties.getInt(key, DEFAULT_MAX_SESSION_COUNT_WORKING);
|
||||
int newWorkingMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_WORKING);
|
||||
if (mMaxBucketSessionCounts[WORKING_INDEX] != newWorkingMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[WORKING_INDEX] = newWorkingMaxSessionCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_SESSION_COUNT_FREQUENT:
|
||||
MAX_SESSION_COUNT_FREQUENT =
|
||||
properties.getInt(key, DEFAULT_MAX_SESSION_COUNT_FREQUENT);
|
||||
int newFrequentMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_FREQUENT);
|
||||
if (mMaxBucketSessionCounts[FREQUENT_INDEX] != newFrequentMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[FREQUENT_INDEX] = newFrequentMaxSessionCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_SESSION_COUNT_RARE:
|
||||
MAX_SESSION_COUNT_RARE = properties.getInt(key, DEFAULT_MAX_SESSION_COUNT_RARE);
|
||||
int newRareMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_RARE);
|
||||
if (mMaxBucketSessionCounts[RARE_INDEX] != newRareMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[RARE_INDEX] = newRareMaxSessionCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MAX_SESSION_COUNT_RESTRICTED:
|
||||
MAX_SESSION_COUNT_RESTRICTED =
|
||||
properties.getInt(key, DEFAULT_MAX_SESSION_COUNT_RESTRICTED);
|
||||
int newRestrictedMaxSessionCount = Math.max(0, MAX_SESSION_COUNT_RESTRICTED);
|
||||
if (mMaxBucketSessionCounts[RESTRICTED_INDEX] != newRestrictedMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[RESTRICTED_INDEX] = newRestrictedMaxSessionCount;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_TIMING_SESSION_COALESCING_DURATION_MS:
|
||||
TIMING_SESSION_COALESCING_DURATION_MS =
|
||||
properties.getLong(key, DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS);
|
||||
long newSessionCoalescingDurationMs = Math.min(15 * MINUTE_IN_MILLIS,
|
||||
Math.max(0, TIMING_SESSION_COALESCING_DURATION_MS));
|
||||
if (mTimingSessionCoalescingDurationMs != newSessionCoalescingDurationMs) {
|
||||
mTimingSessionCoalescingDurationMs = newSessionCoalescingDurationMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
break;
|
||||
case KEY_MIN_QUOTA_CHECK_DELAY_MS:
|
||||
MIN_QUOTA_CHECK_DELAY_MS =
|
||||
properties.getLong(key, DEFAULT_MIN_QUOTA_CHECK_DELAY_MS);
|
||||
// We don't need to re-evaluate execution stats or constraint status for this.
|
||||
// Limit the delay to the range [0, 15] minutes.
|
||||
mInQuotaAlarmListener.setMinQuotaCheckDelayMs(
|
||||
Math.min(15 * MINUTE_IN_MILLIS, Math.max(0, MIN_QUOTA_CHECK_DELAY_MS)));
|
||||
break;
|
||||
}
|
||||
|
||||
ALLOWED_TIME_PER_PERIOD_MS = mParser.getDurationMillis(
|
||||
KEY_ALLOWED_TIME_PER_PERIOD_MS, DEFAULT_ALLOWED_TIME_PER_PERIOD_MS);
|
||||
IN_QUOTA_BUFFER_MS = mParser.getDurationMillis(
|
||||
KEY_IN_QUOTA_BUFFER_MS, DEFAULT_IN_QUOTA_BUFFER_MS);
|
||||
WINDOW_SIZE_ACTIVE_MS = mParser.getDurationMillis(
|
||||
KEY_WINDOW_SIZE_ACTIVE_MS, DEFAULT_WINDOW_SIZE_ACTIVE_MS);
|
||||
WINDOW_SIZE_WORKING_MS = mParser.getDurationMillis(
|
||||
KEY_WINDOW_SIZE_WORKING_MS, DEFAULT_WINDOW_SIZE_WORKING_MS);
|
||||
WINDOW_SIZE_FREQUENT_MS = mParser.getDurationMillis(
|
||||
KEY_WINDOW_SIZE_FREQUENT_MS, DEFAULT_WINDOW_SIZE_FREQUENT_MS);
|
||||
WINDOW_SIZE_RARE_MS = mParser.getDurationMillis(
|
||||
KEY_WINDOW_SIZE_RARE_MS, DEFAULT_WINDOW_SIZE_RARE_MS);
|
||||
WINDOW_SIZE_RESTRICTED_MS = mParser.getDurationMillis(
|
||||
KEY_WINDOW_SIZE_RESTRICTED_MS, DEFAULT_WINDOW_SIZE_RESTRICTED_MS);
|
||||
MAX_EXECUTION_TIME_MS = mParser.getDurationMillis(
|
||||
KEY_MAX_EXECUTION_TIME_MS, DEFAULT_MAX_EXECUTION_TIME_MS);
|
||||
MAX_JOB_COUNT_ACTIVE = mParser.getInt(
|
||||
KEY_MAX_JOB_COUNT_ACTIVE, DEFAULT_MAX_JOB_COUNT_ACTIVE);
|
||||
MAX_JOB_COUNT_WORKING = mParser.getInt(
|
||||
KEY_MAX_JOB_COUNT_WORKING, DEFAULT_MAX_JOB_COUNT_WORKING);
|
||||
MAX_JOB_COUNT_FREQUENT = mParser.getInt(
|
||||
KEY_MAX_JOB_COUNT_FREQUENT, DEFAULT_MAX_JOB_COUNT_FREQUENT);
|
||||
MAX_JOB_COUNT_RARE = mParser.getInt(
|
||||
KEY_MAX_JOB_COUNT_RARE, DEFAULT_MAX_JOB_COUNT_RARE);
|
||||
MAX_JOB_COUNT_RESTRICTED = mParser.getInt(
|
||||
KEY_MAX_JOB_COUNT_RESTRICTED, DEFAULT_MAX_JOB_COUNT_RESTRICTED);
|
||||
RATE_LIMITING_WINDOW_MS = mParser.getLong(
|
||||
KEY_RATE_LIMITING_WINDOW_MS, DEFAULT_RATE_LIMITING_WINDOW_MS);
|
||||
MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = mParser.getInt(
|
||||
KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
MAX_SESSION_COUNT_ACTIVE = mParser.getInt(
|
||||
KEY_MAX_SESSION_COUNT_ACTIVE, DEFAULT_MAX_SESSION_COUNT_ACTIVE);
|
||||
MAX_SESSION_COUNT_WORKING = mParser.getInt(
|
||||
KEY_MAX_SESSION_COUNT_WORKING, DEFAULT_MAX_SESSION_COUNT_WORKING);
|
||||
MAX_SESSION_COUNT_FREQUENT = mParser.getInt(
|
||||
KEY_MAX_SESSION_COUNT_FREQUENT, DEFAULT_MAX_SESSION_COUNT_FREQUENT);
|
||||
MAX_SESSION_COUNT_RARE = mParser.getInt(
|
||||
KEY_MAX_SESSION_COUNT_RARE, DEFAULT_MAX_SESSION_COUNT_RARE);
|
||||
MAX_SESSION_COUNT_RESTRICTED = mParser.getInt(
|
||||
KEY_MAX_SESSION_COUNT_RESTRICTED, DEFAULT_MAX_SESSION_COUNT_RESTRICTED);
|
||||
MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = mParser.getInt(
|
||||
KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
TIMING_SESSION_COALESCING_DURATION_MS = mParser.getLong(
|
||||
KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS);
|
||||
MIN_QUOTA_CHECK_DELAY_MS = mParser.getDurationMillis(KEY_MIN_QUOTA_CHECK_DELAY_MS,
|
||||
DEFAULT_MIN_QUOTA_CHECK_DELAY_MS);
|
||||
|
||||
updateConstants();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateConstants() {
|
||||
synchronized (mLock) {
|
||||
boolean changed = false;
|
||||
private void updateExecutionPeriodConstantsLocked() {
|
||||
if (mExecutionPeriodConstantsUpdated) {
|
||||
return;
|
||||
}
|
||||
mExecutionPeriodConstantsUpdated = true;
|
||||
|
||||
long newMaxExecutionTimeMs = Math.max(MIN_MAX_EXECUTION_TIME_MS,
|
||||
Math.min(MAX_PERIOD_MS, MAX_EXECUTION_TIME_MS));
|
||||
if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
|
||||
mMaxExecutionTimeMs = newMaxExecutionTimeMs;
|
||||
mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
|
||||
changed = true;
|
||||
}
|
||||
long newAllowedTimeMs = Math.min(mMaxExecutionTimeMs,
|
||||
Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_MS));
|
||||
if (mAllowedTimePerPeriodMs != newAllowedTimeMs) {
|
||||
mAllowedTimePerPeriodMs = newAllowedTimeMs;
|
||||
mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
|
||||
changed = true;
|
||||
}
|
||||
// Make sure quota buffer is non-negative, not greater than allowed time per period,
|
||||
// and no more than 5 minutes.
|
||||
long newQuotaBufferMs = Math.max(0, Math.min(mAllowedTimePerPeriodMs,
|
||||
Math.min(5 * MINUTE_IN_MILLIS, IN_QUOTA_BUFFER_MS)));
|
||||
if (mQuotaBufferMs != newQuotaBufferMs) {
|
||||
mQuotaBufferMs = newQuotaBufferMs;
|
||||
mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
|
||||
mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
|
||||
changed = true;
|
||||
}
|
||||
long newActivePeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_ACTIVE_MS));
|
||||
if (mBucketPeriodsMs[ACTIVE_INDEX] != newActivePeriodMs) {
|
||||
mBucketPeriodsMs[ACTIVE_INDEX] = newActivePeriodMs;
|
||||
changed = true;
|
||||
}
|
||||
long newWorkingPeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_WORKING_MS));
|
||||
if (mBucketPeriodsMs[WORKING_INDEX] != newWorkingPeriodMs) {
|
||||
mBucketPeriodsMs[WORKING_INDEX] = newWorkingPeriodMs;
|
||||
changed = true;
|
||||
}
|
||||
long newFrequentPeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_FREQUENT_MS));
|
||||
if (mBucketPeriodsMs[FREQUENT_INDEX] != newFrequentPeriodMs) {
|
||||
mBucketPeriodsMs[FREQUENT_INDEX] = newFrequentPeriodMs;
|
||||
changed = true;
|
||||
}
|
||||
long newRarePeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_RARE_MS));
|
||||
if (mBucketPeriodsMs[RARE_INDEX] != newRarePeriodMs) {
|
||||
mBucketPeriodsMs[RARE_INDEX] = newRarePeriodMs;
|
||||
changed = true;
|
||||
}
|
||||
// Fit in the range [allowed time (10 mins), 1 week].
|
||||
long newRestrictedPeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(7 * 24 * 60 * MINUTE_IN_MILLIS, WINDOW_SIZE_RESTRICTED_MS));
|
||||
if (mBucketPeriodsMs[RESTRICTED_INDEX] != newRestrictedPeriodMs) {
|
||||
mBucketPeriodsMs[RESTRICTED_INDEX] = newRestrictedPeriodMs;
|
||||
changed = true;
|
||||
}
|
||||
long newRateLimitingWindowMs = Math.min(MAX_PERIOD_MS,
|
||||
Math.max(MIN_RATE_LIMITING_WINDOW_MS, RATE_LIMITING_WINDOW_MS));
|
||||
if (mRateLimitingWindowMs != newRateLimitingWindowMs) {
|
||||
mRateLimitingWindowMs = newRateLimitingWindowMs;
|
||||
changed = true;
|
||||
}
|
||||
int newMaxJobCountPerRateLimitingWindow = Math.max(
|
||||
MIN_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
if (mMaxJobCountPerRateLimitingWindow != newMaxJobCountPerRateLimitingWindow) {
|
||||
mMaxJobCountPerRateLimitingWindow = newMaxJobCountPerRateLimitingWindow;
|
||||
changed = true;
|
||||
}
|
||||
int newActiveMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_ACTIVE);
|
||||
if (mMaxBucketJobCounts[ACTIVE_INDEX] != newActiveMaxJobCount) {
|
||||
mMaxBucketJobCounts[ACTIVE_INDEX] = newActiveMaxJobCount;
|
||||
changed = true;
|
||||
}
|
||||
int newWorkingMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_WORKING);
|
||||
if (mMaxBucketJobCounts[WORKING_INDEX] != newWorkingMaxJobCount) {
|
||||
mMaxBucketJobCounts[WORKING_INDEX] = newWorkingMaxJobCount;
|
||||
changed = true;
|
||||
}
|
||||
int newFrequentMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_FREQUENT);
|
||||
if (mMaxBucketJobCounts[FREQUENT_INDEX] != newFrequentMaxJobCount) {
|
||||
mMaxBucketJobCounts[FREQUENT_INDEX] = newFrequentMaxJobCount;
|
||||
changed = true;
|
||||
}
|
||||
int newRareMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RARE);
|
||||
if (mMaxBucketJobCounts[RARE_INDEX] != newRareMaxJobCount) {
|
||||
mMaxBucketJobCounts[RARE_INDEX] = newRareMaxJobCount;
|
||||
changed = true;
|
||||
}
|
||||
int newRestrictedMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT,
|
||||
MAX_JOB_COUNT_RESTRICTED);
|
||||
if (mMaxBucketJobCounts[RESTRICTED_INDEX] != newRestrictedMaxJobCount) {
|
||||
mMaxBucketJobCounts[RESTRICTED_INDEX] = newRestrictedMaxJobCount;
|
||||
changed = true;
|
||||
}
|
||||
int newMaxSessionCountPerRateLimitPeriod = Math.max(
|
||||
MIN_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
if (mMaxSessionCountPerRateLimitingWindow != newMaxSessionCountPerRateLimitPeriod) {
|
||||
mMaxSessionCountPerRateLimitingWindow = newMaxSessionCountPerRateLimitPeriod;
|
||||
changed = true;
|
||||
}
|
||||
int newActiveMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_ACTIVE);
|
||||
if (mMaxBucketSessionCounts[ACTIVE_INDEX] != newActiveMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[ACTIVE_INDEX] = newActiveMaxSessionCount;
|
||||
changed = true;
|
||||
}
|
||||
int newWorkingMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_WORKING);
|
||||
if (mMaxBucketSessionCounts[WORKING_INDEX] != newWorkingMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[WORKING_INDEX] = newWorkingMaxSessionCount;
|
||||
changed = true;
|
||||
}
|
||||
int newFrequentMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_FREQUENT);
|
||||
if (mMaxBucketSessionCounts[FREQUENT_INDEX] != newFrequentMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[FREQUENT_INDEX] = newFrequentMaxSessionCount;
|
||||
changed = true;
|
||||
}
|
||||
int newRareMaxSessionCount =
|
||||
Math.max(MIN_BUCKET_SESSION_COUNT, MAX_SESSION_COUNT_RARE);
|
||||
if (mMaxBucketSessionCounts[RARE_INDEX] != newRareMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[RARE_INDEX] = newRareMaxSessionCount;
|
||||
changed = true;
|
||||
}
|
||||
int newRestrictedMaxSessionCount = Math.max(0, MAX_SESSION_COUNT_RESTRICTED);
|
||||
if (mMaxBucketSessionCounts[RESTRICTED_INDEX] != newRestrictedMaxSessionCount) {
|
||||
mMaxBucketSessionCounts[RESTRICTED_INDEX] = newRestrictedMaxSessionCount;
|
||||
changed = true;
|
||||
}
|
||||
long newSessionCoalescingDurationMs = Math.min(15 * MINUTE_IN_MILLIS,
|
||||
Math.max(0, TIMING_SESSION_COALESCING_DURATION_MS));
|
||||
if (mTimingSessionCoalescingDurationMs != newSessionCoalescingDurationMs) {
|
||||
mTimingSessionCoalescingDurationMs = newSessionCoalescingDurationMs;
|
||||
changed = true;
|
||||
}
|
||||
// Don't set changed to true for this one since we don't need to re-evaluate
|
||||
// execution stats or constraint status. Limit the delay to the range [0, 15]
|
||||
// minutes.
|
||||
mInQuotaAlarmListener.setMinQuotaCheckDelayMs(
|
||||
Math.min(15 * MINUTE_IN_MILLIS, Math.max(0, MIN_QUOTA_CHECK_DELAY_MS)));
|
||||
// Query the values as an atomic set.
|
||||
final DeviceConfig.Properties properties = DeviceConfig.getProperties(
|
||||
DeviceConfig.NAMESPACE_JOB_SCHEDULER,
|
||||
KEY_ALLOWED_TIME_PER_PERIOD_MS, KEY_IN_QUOTA_BUFFER_MS,
|
||||
KEY_MAX_EXECUTION_TIME_MS, KEY_WINDOW_SIZE_ACTIVE_MS,
|
||||
KEY_WINDOW_SIZE_WORKING_MS,
|
||||
KEY_WINDOW_SIZE_FREQUENT_MS, KEY_WINDOW_SIZE_RARE_MS,
|
||||
KEY_WINDOW_SIZE_RESTRICTED_MS);
|
||||
ALLOWED_TIME_PER_PERIOD_MS =
|
||||
properties.getLong(KEY_ALLOWED_TIME_PER_PERIOD_MS,
|
||||
DEFAULT_ALLOWED_TIME_PER_PERIOD_MS);
|
||||
IN_QUOTA_BUFFER_MS = properties.getLong(KEY_IN_QUOTA_BUFFER_MS,
|
||||
DEFAULT_IN_QUOTA_BUFFER_MS);
|
||||
MAX_EXECUTION_TIME_MS = properties.getLong(KEY_MAX_EXECUTION_TIME_MS,
|
||||
DEFAULT_MAX_EXECUTION_TIME_MS);
|
||||
WINDOW_SIZE_ACTIVE_MS = properties.getLong(KEY_WINDOW_SIZE_ACTIVE_MS,
|
||||
DEFAULT_WINDOW_SIZE_ACTIVE_MS);
|
||||
WINDOW_SIZE_WORKING_MS =
|
||||
properties.getLong(KEY_WINDOW_SIZE_WORKING_MS, DEFAULT_WINDOW_SIZE_WORKING_MS);
|
||||
WINDOW_SIZE_FREQUENT_MS =
|
||||
properties.getLong(KEY_WINDOW_SIZE_FREQUENT_MS,
|
||||
DEFAULT_WINDOW_SIZE_FREQUENT_MS);
|
||||
WINDOW_SIZE_RARE_MS = properties.getLong(KEY_WINDOW_SIZE_RARE_MS,
|
||||
DEFAULT_WINDOW_SIZE_RARE_MS);
|
||||
WINDOW_SIZE_RESTRICTED_MS =
|
||||
properties.getLong(KEY_WINDOW_SIZE_RESTRICTED_MS,
|
||||
DEFAULT_WINDOW_SIZE_RESTRICTED_MS);
|
||||
|
||||
if (changed) {
|
||||
// Update job bookkeeping out of band.
|
||||
JobSchedulerBackgroundThread.getHandler().post(() -> {
|
||||
synchronized (mLock) {
|
||||
invalidateAllExecutionStatsLocked();
|
||||
maybeUpdateAllConstraintsLocked();
|
||||
}
|
||||
});
|
||||
}
|
||||
long newMaxExecutionTimeMs = Math.max(MIN_MAX_EXECUTION_TIME_MS,
|
||||
Math.min(MAX_PERIOD_MS, MAX_EXECUTION_TIME_MS));
|
||||
if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
|
||||
mMaxExecutionTimeMs = newMaxExecutionTimeMs;
|
||||
mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
long newAllowedTimeMs = Math.min(mMaxExecutionTimeMs,
|
||||
Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_MS));
|
||||
if (mAllowedTimePerPeriodMs != newAllowedTimeMs) {
|
||||
mAllowedTimePerPeriodMs = newAllowedTimeMs;
|
||||
mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
// Make sure quota buffer is non-negative, not greater than allowed time per period,
|
||||
// and no more than 5 minutes.
|
||||
long newQuotaBufferMs = Math.max(0, Math.min(mAllowedTimePerPeriodMs,
|
||||
Math.min(5 * MINUTE_IN_MILLIS, IN_QUOTA_BUFFER_MS)));
|
||||
if (mQuotaBufferMs != newQuotaBufferMs) {
|
||||
mQuotaBufferMs = newQuotaBufferMs;
|
||||
mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
|
||||
mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
long newActivePeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_ACTIVE_MS));
|
||||
if (mBucketPeriodsMs[ACTIVE_INDEX] != newActivePeriodMs) {
|
||||
mBucketPeriodsMs[ACTIVE_INDEX] = newActivePeriodMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
long newWorkingPeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_WORKING_MS));
|
||||
if (mBucketPeriodsMs[WORKING_INDEX] != newWorkingPeriodMs) {
|
||||
mBucketPeriodsMs[WORKING_INDEX] = newWorkingPeriodMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
long newFrequentPeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_FREQUENT_MS));
|
||||
if (mBucketPeriodsMs[FREQUENT_INDEX] != newFrequentPeriodMs) {
|
||||
mBucketPeriodsMs[FREQUENT_INDEX] = newFrequentPeriodMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
long newRarePeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(MAX_PERIOD_MS, WINDOW_SIZE_RARE_MS));
|
||||
if (mBucketPeriodsMs[RARE_INDEX] != newRarePeriodMs) {
|
||||
mBucketPeriodsMs[RARE_INDEX] = newRarePeriodMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
// Fit in the range [allowed time (10 mins), 1 week].
|
||||
long newRestrictedPeriodMs = Math.max(mAllowedTimePerPeriodMs,
|
||||
Math.min(7 * 24 * 60 * MINUTE_IN_MILLIS, WINDOW_SIZE_RESTRICTED_MS));
|
||||
if (mBucketPeriodsMs[RESTRICTED_INDEX] != newRestrictedPeriodMs) {
|
||||
mBucketPeriodsMs[RESTRICTED_INDEX] = newRestrictedPeriodMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRateLimitingConstantsLocked() {
|
||||
if (mRateLimitingConstantsUpdated) {
|
||||
return;
|
||||
}
|
||||
mRateLimitingConstantsUpdated = true;
|
||||
|
||||
// Query the values as an atomic set.
|
||||
final DeviceConfig.Properties properties = DeviceConfig.getProperties(
|
||||
DeviceConfig.NAMESPACE_JOB_SCHEDULER,
|
||||
KEY_RATE_LIMITING_WINDOW_MS, KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
|
||||
RATE_LIMITING_WINDOW_MS =
|
||||
properties.getLong(KEY_RATE_LIMITING_WINDOW_MS,
|
||||
DEFAULT_RATE_LIMITING_WINDOW_MS);
|
||||
|
||||
MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
|
||||
properties.getInt(KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
|
||||
MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
|
||||
properties.getInt(KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
|
||||
long newRateLimitingWindowMs = Math.min(MAX_PERIOD_MS,
|
||||
Math.max(MIN_RATE_LIMITING_WINDOW_MS, RATE_LIMITING_WINDOW_MS));
|
||||
if (mRateLimitingWindowMs != newRateLimitingWindowMs) {
|
||||
mRateLimitingWindowMs = newRateLimitingWindowMs;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
int newMaxJobCountPerRateLimitingWindow = Math.max(
|
||||
MIN_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
if (mMaxJobCountPerRateLimitingWindow != newMaxJobCountPerRateLimitingWindow) {
|
||||
mMaxJobCountPerRateLimitingWindow = newMaxJobCountPerRateLimitingWindow;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
int newMaxSessionCountPerRateLimitPeriod = Math.max(
|
||||
MIN_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
|
||||
if (mMaxSessionCountPerRateLimitingWindow != newMaxSessionCountPerRateLimitPeriod) {
|
||||
mMaxSessionCountPerRateLimitingWindow = newMaxSessionCountPerRateLimitPeriod;
|
||||
mShouldReevaluateConstraints = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2633,6 +2730,11 @@ public final class QuotaController extends StateController {
|
||||
return mMaxSessionCountPerRateLimitingWindow;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
long getMinQuotaCheckDelayMs() {
|
||||
return mInQuotaAlarmListener.mMinQuotaCheckDelayMs;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
long getRateLimitingWindowMs() {
|
||||
return mRateLimitingWindowMs;
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.DEBUG;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -84,6 +86,13 @@ public abstract class StateController {
|
||||
public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
|
||||
}
|
||||
|
||||
/** Notice that updated configuration constants are about to be read. */
|
||||
public void prepareForUpdatedConstantsLocked() {}
|
||||
|
||||
/** Process the specified constant and update internal constants if relevant. */
|
||||
public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
|
||||
@NonNull String key) {}
|
||||
|
||||
/**
|
||||
* Called when the JobScheduler.Constants are updated.
|
||||
*/
|
||||
|
||||
@@ -11887,21 +11887,6 @@ public final class Settings {
|
||||
*/
|
||||
public static final String POWER_MANAGER_CONSTANTS = "power_manager_constants";
|
||||
|
||||
/**
|
||||
* Job scheduler QuotaController specific settings.
|
||||
* This is encoded as a key=value list, separated by commas. Ex:
|
||||
*
|
||||
* "max_job_count_working=5,max_job_count_rare=2"
|
||||
*
|
||||
* <p>
|
||||
* Type: string
|
||||
*
|
||||
* @hide
|
||||
* @see com.android.server.job.JobSchedulerService.Constants
|
||||
*/
|
||||
public static final String JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS =
|
||||
"job_scheduler_quota_controller_constants";
|
||||
|
||||
/**
|
||||
* ShortcutManager specific settings.
|
||||
* This is encoded as a key=value list, separated by commas. Ex:
|
||||
|
||||
@@ -510,7 +510,7 @@ message GlobalSettingsProto {
|
||||
optional IntentFirewall intent_firewall = 65;
|
||||
|
||||
reserved 66; // job_scheduler_constants
|
||||
optional SettingProto job_scheduler_quota_controller_constants = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
reserved 149; // job_scheduler_quota_controller_constants
|
||||
reserved 150; // job_scheduler_time_controller_constants
|
||||
|
||||
optional SettingProto keep_profile_in_background = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
|
||||
|
||||
@@ -862,9 +862,6 @@ class SettingsProtoDumpUtil {
|
||||
GlobalSettingsProto.IntentFirewall.UPDATE_METADATA_URL);
|
||||
p.end(intentFirewallToken);
|
||||
|
||||
dumpSetting(s, p,
|
||||
Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS,
|
||||
GlobalSettingsProto.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS);
|
||||
dumpSetting(s, p,
|
||||
Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
|
||||
GlobalSettingsProto.KEEP_PROFILE_IN_BACKGROUND);
|
||||
|
||||
@@ -309,7 +309,6 @@ public class SettingsBackupTest {
|
||||
Settings.Global.INSTANT_APP_DEXOPT_ENABLED,
|
||||
Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL,
|
||||
Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL,
|
||||
Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS,
|
||||
Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
|
||||
Settings.Global.KERNEL_CPU_THREAD_READER,
|
||||
Settings.Global.LANG_ID_UPDATE_CONTENT_URL,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
|
||||
@@ -27,6 +28,7 @@ import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
@@ -39,6 +41,7 @@ import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -68,6 +71,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
@@ -78,6 +82,7 @@ import com.android.server.job.JobSchedulerService.Constants;
|
||||
import com.android.server.job.JobServiceContext;
|
||||
import com.android.server.job.JobStore;
|
||||
import com.android.server.job.controllers.QuotaController.ExecutionStats;
|
||||
import com.android.server.job.controllers.QuotaController.QcConstants;
|
||||
import com.android.server.job.controllers.QuotaController.TimingSession;
|
||||
import com.android.server.usage.AppStandbyInternal;
|
||||
|
||||
@@ -86,16 +91,19 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class QuotaControllerTest {
|
||||
@@ -113,6 +121,7 @@ public class QuotaControllerTest {
|
||||
private QuotaController.QcConstants mQcConstants;
|
||||
private int mSourceUid;
|
||||
private IUidObserver mUidObserver;
|
||||
DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder;
|
||||
|
||||
private MockitoSession mMockingSession;
|
||||
@Mock
|
||||
@@ -133,6 +142,7 @@ public class QuotaControllerTest {
|
||||
mMockingSession = mockitoSession()
|
||||
.initMocks(this)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.spyStatic(DeviceConfig.class)
|
||||
.mockStatic(LocalServices.class)
|
||||
.startMocking();
|
||||
|
||||
@@ -164,6 +174,18 @@ public class QuotaControllerTest {
|
||||
// Used in QuotaController.Handler.
|
||||
mJobStore = JobStore.initAndGetForTesting(mContext, mContext.getFilesDir());
|
||||
when(mJobSchedulerService.getJobStore()).thenReturn(mJobStore);
|
||||
// Used in QuotaController.QcConstants
|
||||
doAnswer((Answer<Void>) invocationOnMock -> null)
|
||||
.when(() -> DeviceConfig.addOnPropertiesChangedListener(
|
||||
anyString(), any(Executor.class),
|
||||
any(DeviceConfig.OnPropertiesChangedListener.class)));
|
||||
mDeviceConfigPropertiesBuilder =
|
||||
new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
|
||||
doAnswer(
|
||||
(Answer<DeviceConfig.Properties>) invocationOnMock
|
||||
-> mDeviceConfigPropertiesBuilder.build())
|
||||
.when(() -> DeviceConfig.getProperties(
|
||||
eq(DeviceConfig.NAMESPACE_JOB_SCHEDULER), ArgumentMatchers.<String>any()));
|
||||
|
||||
// Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
|
||||
// in the past, and QuotaController sometimes floors values at 0, so if the test time
|
||||
@@ -313,6 +335,18 @@ public class QuotaControllerTest {
|
||||
return new TimingSession(start, start + duration, count);
|
||||
}
|
||||
|
||||
private void setDeviceConfigLong(String key, long val) {
|
||||
mQuotaController.prepareForUpdatedConstantsLocked();
|
||||
mDeviceConfigPropertiesBuilder.setLong(key, val);
|
||||
mQcConstants.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
|
||||
}
|
||||
|
||||
private void setDeviceConfigInt(String key, int val) {
|
||||
mQuotaController.prepareForUpdatedConstantsLocked();
|
||||
mDeviceConfigPropertiesBuilder.setInt(key, val);
|
||||
mQcConstants.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveTimingSession() {
|
||||
assertNull(mQuotaController.getTimingSessions(0, "com.android.test"));
|
||||
@@ -858,8 +892,7 @@ public class QuotaControllerTest {
|
||||
advanceElapsedClock(40 * MINUTE_IN_MILLIS);
|
||||
}
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 0;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS, 0);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -871,8 +904,7 @@ public class QuotaControllerTest {
|
||||
assertEquals(160, mQuotaController.getExecutionStatsLocked(
|
||||
0, "com.android.test", RARE_INDEX).sessionCountInWindow);
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 500;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS, 500);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -884,8 +916,7 @@ public class QuotaControllerTest {
|
||||
assertEquals(110, mQuotaController.getExecutionStatsLocked(
|
||||
0, "com.android.test", RARE_INDEX).sessionCountInWindow);
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 1000;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS, 1000);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -897,8 +928,8 @@ public class QuotaControllerTest {
|
||||
assertEquals(110, mQuotaController.getExecutionStatsLocked(
|
||||
0, "com.android.test", RARE_INDEX).sessionCountInWindow);
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 5 * SECOND_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
5 * SECOND_IN_MILLIS);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -910,8 +941,8 @@ public class QuotaControllerTest {
|
||||
assertEquals(70, mQuotaController.getExecutionStatsLocked(
|
||||
0, "com.android.test", RARE_INDEX).sessionCountInWindow);
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = MINUTE_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
MINUTE_IN_MILLIS);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -923,8 +954,8 @@ public class QuotaControllerTest {
|
||||
assertEquals(20, mQuotaController.getExecutionStatsLocked(
|
||||
0, "com.android.test", RARE_INDEX).sessionCountInWindow);
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 5 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
5 * MINUTE_IN_MILLIS);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -936,8 +967,8 @@ public class QuotaControllerTest {
|
||||
assertEquals(10, mQuotaController.getExecutionStatsLocked(
|
||||
0, "com.android.test", RARE_INDEX).sessionCountInWindow);
|
||||
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 15 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
15 * MINUTE_IN_MILLIS);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -951,8 +982,7 @@ public class QuotaControllerTest {
|
||||
|
||||
// QuotaController caps the duration at 15 minutes, so there shouldn't be any difference
|
||||
// between an hour and 15 minutes.
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = HOUR_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS, HOUR_IN_MILLIS);
|
||||
|
||||
mQuotaController.invalidateAllExecutionStatsLocked();
|
||||
assertEquals(0, mQuotaController.getExecutionStatsLocked(
|
||||
@@ -994,8 +1024,7 @@ public class QuotaControllerTest {
|
||||
// Advance clock so that the working stats shouldn't be the same.
|
||||
advanceElapsedClock(MINUTE_IN_MILLIS);
|
||||
// Change frequent bucket size so that the stats need to be recalculated.
|
||||
mQcConstants.WINDOW_SIZE_FREQUENT_MS = 6 * HOUR_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_FREQUENT_MS, 6 * HOUR_IN_MILLIS);
|
||||
|
||||
ExecutionStats expectedStats = new ExecutionStats();
|
||||
expectedStats.windowSizeMs = originalStatsActive.windowSizeMs;
|
||||
@@ -1413,11 +1442,10 @@ public class QuotaControllerTest {
|
||||
public void testIsWithinQuotaLocked_TimingSession() {
|
||||
setDischarging();
|
||||
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
|
||||
mQcConstants.MAX_SESSION_COUNT_RARE = 3;
|
||||
mQcConstants.MAX_SESSION_COUNT_FREQUENT = 4;
|
||||
mQcConstants.MAX_SESSION_COUNT_WORKING = 5;
|
||||
mQcConstants.MAX_SESSION_COUNT_ACTIVE = 6;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_RARE, 3);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_FREQUENT, 4);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_WORKING, 5);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_ACTIVE, 6);
|
||||
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
mQuotaController.saveTimingSession(0, "com.android.test",
|
||||
@@ -1629,8 +1657,7 @@ public class QuotaControllerTest {
|
||||
final int standbyBucket = RARE_INDEX;
|
||||
|
||||
// Prevent timing session throttling from affecting the test.
|
||||
mQcConstants.MAX_SESSION_COUNT_RARE = 50;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_RARE, 50);
|
||||
|
||||
// No sessions saved yet.
|
||||
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", standbyBucket);
|
||||
@@ -1749,9 +1776,8 @@ public class QuotaControllerTest {
|
||||
public void testMaybeScheduleStartAlarmLocked_JobCount_RateLimitingWindow() {
|
||||
// Set rate limiting period different from allowed time to confirm code sets based on
|
||||
// the former.
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = 10 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.RATE_LIMITING_WINDOW_MS = 5 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS, 10 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_RATE_LIMITING_WINDOW_MS, 5 * MINUTE_IN_MILLIS);
|
||||
|
||||
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
|
||||
final int standbyBucket = WORKING_INDEX;
|
||||
@@ -1790,8 +1816,9 @@ public class QuotaControllerTest {
|
||||
@Test
|
||||
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedBufferSize() {
|
||||
// Make sure any new value is used correctly.
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS *= 2;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_IN_QUOTA_BUFFER_MS,
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS * 2);
|
||||
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
|
||||
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
|
||||
@@ -1800,8 +1827,9 @@ public class QuotaControllerTest {
|
||||
@Test
|
||||
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedAllowedTime() {
|
||||
// Make sure any new value is used correctly.
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS /= 2;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS,
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS / 2);
|
||||
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
|
||||
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
|
||||
@@ -1810,8 +1838,9 @@ public class QuotaControllerTest {
|
||||
@Test
|
||||
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedMaxTime() {
|
||||
// Make sure any new value is used correctly.
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS /= 2;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_MAX_EXECUTION_TIME_MS,
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS / 2);
|
||||
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
|
||||
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
|
||||
@@ -1820,10 +1849,13 @@ public class QuotaControllerTest {
|
||||
@Test
|
||||
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedEverything() {
|
||||
// Make sure any new value is used correctly.
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS *= 2;
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS /= 2;
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS /= 2;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_IN_QUOTA_BUFFER_MS,
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS * 2);
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS,
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS / 2);
|
||||
setDeviceConfigLong(QcConstants.KEY_MAX_EXECUTION_TIME_MS,
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS / 2);
|
||||
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
|
||||
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
|
||||
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
|
||||
@@ -1891,27 +1923,30 @@ public class QuotaControllerTest {
|
||||
|
||||
@Test
|
||||
public void testConstantsUpdating_ValidValues() {
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = 5 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS = 2 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_ACTIVE_MS = 15 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_WORKING_MS = 30 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_FREQUENT_MS = 45 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_RARE_MS = 60 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS = 3 * HOUR_IN_MILLIS;
|
||||
mQcConstants.MAX_JOB_COUNT_ACTIVE = 5000;
|
||||
mQcConstants.MAX_JOB_COUNT_WORKING = 4000;
|
||||
mQcConstants.MAX_JOB_COUNT_FREQUENT = 3000;
|
||||
mQcConstants.MAX_JOB_COUNT_RARE = 2000;
|
||||
mQcConstants.RATE_LIMITING_WINDOW_MS = 15 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 500;
|
||||
mQcConstants.MAX_SESSION_COUNT_ACTIVE = 500;
|
||||
mQcConstants.MAX_SESSION_COUNT_WORKING = 400;
|
||||
mQcConstants.MAX_SESSION_COUNT_FREQUENT = 300;
|
||||
mQcConstants.MAX_SESSION_COUNT_RARE = 200;
|
||||
mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 50;
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 10 * SECOND_IN_MILLIS;
|
||||
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS, 5 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_IN_QUOTA_BUFFER_MS, 2 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_ACTIVE_MS, 15 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_WORKING_MS, 30 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_FREQUENT_MS, 45 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_RARE_MS, 60 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_RESTRICTED_MS, 120 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_MAX_EXECUTION_TIME_MS, 3 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_ACTIVE, 5000);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_WORKING, 4000);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_FREQUENT, 3000);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_RARE, 2000);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_RESTRICTED, 2000);
|
||||
setDeviceConfigLong(QcConstants.KEY_RATE_LIMITING_WINDOW_MS, 15 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW, 500);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_ACTIVE, 500);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_WORKING, 400);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_FREQUENT, 300);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_RARE, 200);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_RESTRICTED, 100);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW, 50);
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
10 * SECOND_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_MIN_QUOTA_CHECK_DELAY_MS, 7 * MINUTE_IN_MILLIS);
|
||||
|
||||
assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
|
||||
assertEquals(2 * MINUTE_IN_MILLIS, mQuotaController.getInQuotaBufferMs());
|
||||
@@ -1920,6 +1955,8 @@ public class QuotaControllerTest {
|
||||
assertEquals(45 * MINUTE_IN_MILLIS,
|
||||
mQuotaController.getBucketWindowSizes()[FREQUENT_INDEX]);
|
||||
assertEquals(60 * MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RARE_INDEX]);
|
||||
assertEquals(120 * MINUTE_IN_MILLIS,
|
||||
mQuotaController.getBucketWindowSizes()[RESTRICTED_INDEX]);
|
||||
assertEquals(3 * HOUR_IN_MILLIS, mQuotaController.getMaxExecutionTimeMs());
|
||||
assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getRateLimitingWindowMs());
|
||||
assertEquals(500, mQuotaController.getMaxJobCountPerRateLimitingWindow());
|
||||
@@ -1927,39 +1964,44 @@ public class QuotaControllerTest {
|
||||
assertEquals(4000, mQuotaController.getBucketMaxJobCounts()[WORKING_INDEX]);
|
||||
assertEquals(3000, mQuotaController.getBucketMaxJobCounts()[FREQUENT_INDEX]);
|
||||
assertEquals(2000, mQuotaController.getBucketMaxJobCounts()[RARE_INDEX]);
|
||||
assertEquals(2000, mQuotaController.getBucketMaxJobCounts()[RESTRICTED_INDEX]);
|
||||
assertEquals(50, mQuotaController.getMaxSessionCountPerRateLimitingWindow());
|
||||
assertEquals(500, mQuotaController.getBucketMaxSessionCounts()[ACTIVE_INDEX]);
|
||||
assertEquals(400, mQuotaController.getBucketMaxSessionCounts()[WORKING_INDEX]);
|
||||
assertEquals(300, mQuotaController.getBucketMaxSessionCounts()[FREQUENT_INDEX]);
|
||||
assertEquals(200, mQuotaController.getBucketMaxSessionCounts()[RARE_INDEX]);
|
||||
assertEquals(100, mQuotaController.getBucketMaxSessionCounts()[RESTRICTED_INDEX]);
|
||||
assertEquals(10 * SECOND_IN_MILLIS,
|
||||
mQuotaController.getTimingSessionCoalescingDurationMs());
|
||||
assertEquals(7 * MINUTE_IN_MILLIS, mQuotaController.getMinQuotaCheckDelayMs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstantsUpdating_InvalidValues() {
|
||||
// Test negatives/too low.
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_ACTIVE_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_WORKING_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_FREQUENT_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_RARE_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS = -MINUTE_IN_MILLIS;
|
||||
mQcConstants.MAX_JOB_COUNT_ACTIVE = -1;
|
||||
mQcConstants.MAX_JOB_COUNT_WORKING = 1;
|
||||
mQcConstants.MAX_JOB_COUNT_FREQUENT = 1;
|
||||
mQcConstants.MAX_JOB_COUNT_RARE = 1;
|
||||
mQcConstants.RATE_LIMITING_WINDOW_MS = 15 * SECOND_IN_MILLIS;
|
||||
mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 0;
|
||||
mQcConstants.MAX_SESSION_COUNT_ACTIVE = -1;
|
||||
mQcConstants.MAX_SESSION_COUNT_WORKING = 0;
|
||||
mQcConstants.MAX_SESSION_COUNT_FREQUENT = -3;
|
||||
mQcConstants.MAX_SESSION_COUNT_RARE = 0;
|
||||
mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 0;
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = -1;
|
||||
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_IN_QUOTA_BUFFER_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_ACTIVE_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_WORKING_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_FREQUENT_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_RARE_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_RESTRICTED_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_MAX_EXECUTION_TIME_MS, -MINUTE_IN_MILLIS);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_ACTIVE, -1);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_WORKING, 1);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_FREQUENT, 1);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_RARE, 1);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_RESTRICTED, -1);
|
||||
setDeviceConfigLong(QcConstants.KEY_RATE_LIMITING_WINDOW_MS, 15 * SECOND_IN_MILLIS);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW, 0);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_ACTIVE, -1);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_WORKING, 0);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_FREQUENT, -3);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_RARE, 0);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_RESTRICTED, -5);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW, 0);
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS, -1);
|
||||
setDeviceConfigLong(QcConstants.KEY_MIN_QUOTA_CHECK_DELAY_MS, -1);
|
||||
|
||||
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
|
||||
assertEquals(0, mQuotaController.getInQuotaBufferMs());
|
||||
@@ -1967,6 +2009,7 @@ public class QuotaControllerTest {
|
||||
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[WORKING_INDEX]);
|
||||
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[FREQUENT_INDEX]);
|
||||
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RARE_INDEX]);
|
||||
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RESTRICTED_INDEX]);
|
||||
assertEquals(HOUR_IN_MILLIS, mQuotaController.getMaxExecutionTimeMs());
|
||||
assertEquals(30 * SECOND_IN_MILLIS, mQuotaController.getRateLimitingWindowMs());
|
||||
assertEquals(10, mQuotaController.getMaxJobCountPerRateLimitingWindow());
|
||||
@@ -1974,35 +2017,37 @@ public class QuotaControllerTest {
|
||||
assertEquals(10, mQuotaController.getBucketMaxJobCounts()[WORKING_INDEX]);
|
||||
assertEquals(10, mQuotaController.getBucketMaxJobCounts()[FREQUENT_INDEX]);
|
||||
assertEquals(10, mQuotaController.getBucketMaxJobCounts()[RARE_INDEX]);
|
||||
assertEquals(10, mQuotaController.getBucketMaxJobCounts()[RESTRICTED_INDEX]);
|
||||
assertEquals(10, mQuotaController.getMaxSessionCountPerRateLimitingWindow());
|
||||
assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[ACTIVE_INDEX]);
|
||||
assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[WORKING_INDEX]);
|
||||
assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[FREQUENT_INDEX]);
|
||||
assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[RARE_INDEX]);
|
||||
assertEquals(0, mQuotaController.getBucketMaxSessionCounts()[RESTRICTED_INDEX]);
|
||||
assertEquals(0, mQuotaController.getTimingSessionCoalescingDurationMs());
|
||||
assertEquals(0, mQuotaController.getMinQuotaCheckDelayMs());
|
||||
|
||||
// Invalid configurations.
|
||||
// In_QUOTA_BUFFER should never be greater than ALLOWED_TIME_PER_PERIOD
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = 2 * MINUTE_IN_MILLIS;
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS = 5 * MINUTE_IN_MILLIS;
|
||||
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS, 2 * MINUTE_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_IN_QUOTA_BUFFER_MS, 5 * MINUTE_IN_MILLIS);
|
||||
|
||||
assertTrue(mQuotaController.getInQuotaBufferMs()
|
||||
<= mQuotaController.getAllowedTimePerPeriodMs());
|
||||
|
||||
// Test larger than a day. Controller should cap at one day.
|
||||
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.IN_QUOTA_BUFFER_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_ACTIVE_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_WORKING_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_FREQUENT_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.WINDOW_SIZE_RARE_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.MAX_EXECUTION_TIME_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.RATE_LIMITING_WINDOW_MS = 25 * HOUR_IN_MILLIS;
|
||||
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 25 * HOUR_IN_MILLIS;
|
||||
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigLong(QcConstants.KEY_ALLOWED_TIME_PER_PERIOD_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_IN_QUOTA_BUFFER_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_ACTIVE_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_WORKING_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_FREQUENT_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_RARE_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_WINDOW_SIZE_RESTRICTED_MS, 30 * 24 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_MAX_EXECUTION_TIME_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_RATE_LIMITING_WINDOW_MS, 25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_TIMING_SESSION_COALESCING_DURATION_MS,
|
||||
25 * HOUR_IN_MILLIS);
|
||||
setDeviceConfigLong(QcConstants.KEY_MIN_QUOTA_CHECK_DELAY_MS, 25 * HOUR_IN_MILLIS);
|
||||
|
||||
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
|
||||
assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getInQuotaBufferMs());
|
||||
@@ -2010,10 +2055,13 @@ public class QuotaControllerTest {
|
||||
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getBucketWindowSizes()[WORKING_INDEX]);
|
||||
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getBucketWindowSizes()[FREQUENT_INDEX]);
|
||||
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RARE_INDEX]);
|
||||
assertEquals(7 * 24 * HOUR_IN_MILLIS,
|
||||
mQuotaController.getBucketWindowSizes()[RESTRICTED_INDEX]);
|
||||
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getMaxExecutionTimeMs());
|
||||
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getRateLimitingWindowMs());
|
||||
assertEquals(15 * MINUTE_IN_MILLIS,
|
||||
mQuotaController.getTimingSessionCoalescingDurationMs());
|
||||
assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getMinQuotaCheckDelayMs());
|
||||
}
|
||||
|
||||
/** Tests that TimingSessions aren't saved when the device is charging. */
|
||||
@@ -2619,9 +2667,9 @@ public class QuotaControllerTest {
|
||||
doNothing().when(mQuotaController).maybeScheduleCleanupAlarmLocked();
|
||||
|
||||
// Essentially disable session throttling.
|
||||
mQcConstants.MAX_SESSION_COUNT_WORKING =
|
||||
mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = Integer.MAX_VALUE;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_WORKING, Integer.MAX_VALUE);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
Integer.MAX_VALUE);
|
||||
|
||||
final int standbyBucket = WORKING_INDEX;
|
||||
setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
|
||||
@@ -2671,12 +2719,12 @@ public class QuotaControllerTest {
|
||||
doNothing().when(mQuotaController).maybeScheduleCleanupAlarmLocked();
|
||||
|
||||
// Essentially disable job count throttling.
|
||||
mQcConstants.MAX_JOB_COUNT_FREQUENT =
|
||||
mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = Integer.MAX_VALUE;
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_FREQUENT, Integer.MAX_VALUE);
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
|
||||
Integer.MAX_VALUE);
|
||||
// Make sure throttling is because of COUNT_PER_RATE_LIMITING_WINDOW.
|
||||
mQcConstants.MAX_SESSION_COUNT_FREQUENT =
|
||||
mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW + 1;
|
||||
mQcConstants.updateConstants();
|
||||
setDeviceConfigInt(QcConstants.KEY_MAX_SESSION_COUNT_FREQUENT,
|
||||
mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW + 1);
|
||||
|
||||
final int standbyBucket = FREQUENT_INDEX;
|
||||
setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
|
||||
|
||||
Reference in New Issue
Block a user