Creating separate flags for Time/QuotaControllers.
TimeController and QuotaController flags don't have to be changed
atomically with other JobScheduler constants, so it's best to have them
be separate. I think it's best to have the QuotaController constant
change be atomic, which is why the flag is set up as a key/value pair.
Bug: 120793892
Test: atest android.provider.SettingsBackupTest
Test: atest com.android.server.job.controllers.ConnectivityControllerTest
Test: atest com.android.server.job.controllers.QuotaControllerTest
Test: atest com.android.server.job.controllers.StateControllerTest
Test: atest com.android.server.job.controllers.TimeControllerTest
Test: atest CtsJobSchedulerTestCases
Change-Id: I5bf20c37ea87a58bbcf4326f8e81cd6bea0a7c08
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8a21806..b0e980e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11961,6 +11961,36 @@
public static final String JOB_SCHEDULER_CONSTANTS = "job_scheduler_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";
+
+ /**
+ * Job scheduler TimeController specific settings.
+ * This is encoded as a key=value list, separated by commas. Ex:
+ *
+ * "skip_not_ready_jobs=true5,other_key=2"
+ *
+ * <p>
+ * Type: string
+ *
+ * @hide
+ * @see com.android.server.job.JobSchedulerService.Constants
+ */
+ public static final String JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS =
+ "job_scheduler_time_controller_constants";
+
+ /**
* ShortcutManager specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
*
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index b47097d..8f16b41 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -501,7 +501,10 @@
}
optional IntentFirewall intent_firewall = 65;
- optional SettingProto job_scheduler_constants = 66;
+ optional SettingProto job_scheduler_constants = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto job_scheduler_quota_controller_constants = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto job_scheduler_time_controller_constants = 150 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
optional SettingProto keep_profile_in_background = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
message LangId {
@@ -1049,5 +1052,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 149;
+ // Next tag = 151;
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index f4d3c81..61fb811 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -294,6 +294,8 @@
Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL,
Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL,
Settings.Global.JOB_SCHEDULER_CONSTANTS,
+ Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS,
+ Settings.Global.JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS,
Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
Settings.Global.KERNEL_CPU_THREAD_READER,
Settings.Global.LANG_ID_UPDATE_CONTENT_URL,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index cd4f6cf..c94ee0e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -797,6 +797,12 @@
Settings.Global.JOB_SCHEDULER_CONSTANTS,
GlobalSettingsProto.JOB_SCHEDULER_CONSTANTS);
dumpSetting(s, p,
+ Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS,
+ GlobalSettingsProto.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS);
+ dumpSetting(s, p,
+ Settings.Global.JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS,
+ GlobalSettingsProto.JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS);
+ dumpSetting(s, p,
Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
GlobalSettingsProto.KEEP_PROFILE_IN_BACKGROUND);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 3a397cd..b676618 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -464,32 +464,6 @@
private static final String KEY_CONN_CONGESTION_DELAY_FRAC = "conn_congestion_delay_frac";
private static final String KEY_CONN_PREFETCH_RELAX_FRAC = "conn_prefetch_relax_frac";
private static final String KEY_USE_HEARTBEATS = "use_heartbeats";
- private static final String KEY_TIME_CONTROLLER_SKIP_NOT_READY_JOBS =
- "tc_skip_not_ready_jobs";
- private static final String KEY_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS =
- "qc_allowed_time_per_period_ms";
- private static final String KEY_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS =
- "qc_in_quota_buffer_ms";
- private static final String KEY_QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS =
- "qc_window_size_active_ms";
- private static final String KEY_QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS =
- "qc_window_size_working_ms";
- private static final String KEY_QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS =
- "qc_window_size_frequent_ms";
- private static final String KEY_QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS =
- "qc_window_size_rare_ms";
- private static final String KEY_QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS =
- "qc_max_execution_time_ms";
- private static final String KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE =
- "qc_max_job_count_active";
- private static final String KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING =
- "qc_max_job_count_working";
- private static final String KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT =
- "qc_max_job_count_frequent";
- private static final String KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE =
- "qc_max_job_count_rare";
- private static final String KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME =
- "qc_max_count_per_allowed_time";
private static final int DEFAULT_MIN_IDLE_COUNT = 1;
private static final int DEFAULT_MIN_CHARGING_COUNT = 1;
@@ -511,30 +485,6 @@
private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f;
private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f;
private static final boolean DEFAULT_USE_HEARTBEATS = false;
- private static final boolean DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- private static final long DEFAULT_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS =
- 10 * 60 * 1000L; // 10 minutes
- private static final long DEFAULT_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS =
- 30 * 1000L; // 30 seconds
- private static final long DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS =
- 10 * 60 * 1000L; // 10 minutes for ACTIVE -- ACTIVE apps can run jobs at any time
- private static final long DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS =
- 2 * 60 * 60 * 1000L; // 2 hours
- private static final long DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS =
- 8 * 60 * 60 * 1000L; // 8 hours
- private static final long DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS =
- 24 * 60 * 60 * 1000L; // 24 hours
- private static final long DEFAULT_QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS =
- 4 * 60 * 60 * 1000L; // 4 hours
- private static final int DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE =
- 200; // 1200/hr
- private static final int DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING =
- 1200; // 600/hr
- private static final int DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT =
- 1800; // 225/hr
- private static final int DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE =
- 2400; // 100/hr
- private static final int DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME = 20;
/**
* Minimum # of idle jobs that must be ready in order to force the JMS to schedule things
@@ -681,97 +631,6 @@
*/
public boolean USE_HEARTBEATS = DEFAULT_USE_HEARTBEATS;
- /**
- * Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
- * ready now.
- */
- public boolean TIME_CONTROLLER_SKIP_NOT_READY_JOBS =
- DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS;
-
- /** How much time each app will have to run jobs within their standby bucket window. */
- public long QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS =
- DEFAULT_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS;
-
- /**
- * How much time the package should have before transitioning from out-of-quota to in-quota.
- * This should not affect processing if the package is already in-quota.
- */
- public long QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS =
- DEFAULT_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
-
- /**
- * The quota window size of the particular standby bucket. Apps in this standby bucket are
- * expected to run only {@link #QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS} within the past
- * WINDOW_SIZE_MS.
- */
- public long QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS =
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS;
-
- /**
- * The quota window size of the particular standby bucket. Apps in this standby bucket are
- * expected to run only {@link #QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS} within the past
- * WINDOW_SIZE_MS.
- */
- public long QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS =
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS;
-
- /**
- * The quota window size of the particular standby bucket. Apps in this standby bucket are
- * expected to run only {@link #QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS} within the past
- * WINDOW_SIZE_MS.
- */
- public long QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS =
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS;
-
- /**
- * The quota window size of the particular standby bucket. Apps in this standby bucket are
- * expected to run only {@link #QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS} within the past
- * WINDOW_SIZE_MS.
- */
- public long QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS =
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS;
-
- /**
- * The maximum amount of time an app can have its jobs running within a 24 hour window.
- */
- public long QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS =
- DEFAULT_QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS;
-
- /**
- * The maximum number of jobs an app can run within this particular standby bucket's
- * window size.
- */
- public int QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE =
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE;
-
- /**
- * The maximum number of jobs an app can run within this particular standby bucket's
- * window size.
- */
- public int QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING =
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING;
-
- /**
- * The maximum number of jobs an app can run within this particular standby bucket's
- * window size.
- */
- public int QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT =
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT;
-
- /**
- * The maximum number of jobs an app can run within this particular standby bucket's
- * window size.
- */
- public int QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE =
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE;
-
- /**
- * The maximum number of jobs that can run within the past
- * {@link #QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS}.
- */
- public int QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME =
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME;
-
private final KeyValueListParser mParser = new KeyValueListParser(',');
void updateConstantsLocked(String value) {
@@ -835,45 +694,6 @@
CONN_PREFETCH_RELAX_FRAC = mParser.getFloat(KEY_CONN_PREFETCH_RELAX_FRAC,
DEFAULT_CONN_PREFETCH_RELAX_FRAC);
USE_HEARTBEATS = mParser.getBoolean(KEY_USE_HEARTBEATS, DEFAULT_USE_HEARTBEATS);
- TIME_CONTROLLER_SKIP_NOT_READY_JOBS = mParser.getBoolean(
- KEY_TIME_CONTROLLER_SKIP_NOT_READY_JOBS,
- DEFAULT_TIME_CONTROLLER_SKIP_NOT_READY_JOBS);
- QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS,
- DEFAULT_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS);
- QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS,
- DEFAULT_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS);
- QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS,
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS);
- QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS,
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS);
- QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS,
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS);
- QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS,
- DEFAULT_QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS);
- QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS = mParser.getDurationMillis(
- KEY_QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS,
- DEFAULT_QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS);
- QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE = mParser.getInt(
- KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE,
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE);
- QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING = mParser.getInt(
- KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING,
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING);
- QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT = mParser.getInt(
- KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT,
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT);
- QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE = mParser.getInt(
- KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE,
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE);
- QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME = mParser.getInt(
- KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME,
- DEFAULT_QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME);
}
void dump(IndentingPrintWriter pw) {
@@ -916,37 +736,11 @@
pw.printPair(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println();
pw.printPair(KEY_CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC).println();
pw.printPair(KEY_USE_HEARTBEATS, USE_HEARTBEATS).println();
- pw.printPair(KEY_TIME_CONTROLLER_SKIP_NOT_READY_JOBS,
- TIME_CONTROLLER_SKIP_NOT_READY_JOBS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS,
- QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS,
- QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS,
- QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE).println();
- pw.printPair(KEY_QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME).println();
+
pw.decreaseIndent();
}
- void dump(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
+ void dump(ProtoOutputStream proto) {
proto.write(ConstantsProto.MIN_IDLE_COUNT, MIN_IDLE_COUNT);
proto.write(ConstantsProto.MIN_CHARGING_COUNT, MIN_CHARGING_COUNT);
proto.write(ConstantsProto.MIN_BATTERY_NOT_LOW_COUNT, MIN_BATTERY_NOT_LOW_COUNT);
@@ -974,40 +768,6 @@
proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC);
proto.write(ConstantsProto.CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC);
proto.write(ConstantsProto.USE_HEARTBEATS, USE_HEARTBEATS);
-
- final long tcToken = proto.start(ConstantsProto.TIME_CONTROLLER);
- proto.write(ConstantsProto.TimeController.SKIP_NOT_READY_JOBS,
- TIME_CONTROLLER_SKIP_NOT_READY_JOBS);
- proto.end(tcToken);
-
- final long qcToken = proto.start(ConstantsProto.QUOTA_CONTROLLER);
- proto.write(ConstantsProto.QuotaController.ALLOWED_TIME_PER_PERIOD_MS,
- QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS);
- proto.write(ConstantsProto.QuotaController.IN_QUOTA_BUFFER_MS,
- QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS);
- proto.write(ConstantsProto.QuotaController.ACTIVE_WINDOW_SIZE_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS);
- proto.write(ConstantsProto.QuotaController.WORKING_WINDOW_SIZE_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS);
- proto.write(ConstantsProto.QuotaController.FREQUENT_WINDOW_SIZE_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS);
- proto.write(ConstantsProto.QuotaController.RARE_WINDOW_SIZE_MS,
- QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS);
- proto.write(ConstantsProto.QuotaController.MAX_EXECUTION_TIME_MS,
- QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS);
- proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_ACTIVE,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE);
- proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_WORKING,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING);
- proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_FREQUENT,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT);
- proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_RARE,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE);
- proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_PER_ALLOWED_TIME,
- QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME);
- proto.end(qcToken);
-
- proto.end(token);
}
}
@@ -1637,6 +1397,9 @@
public void onBootPhase(int phase) {
if (PHASE_SYSTEM_SERVICES_READY == phase) {
mConstantsObserver.start(getContext().getContentResolver());
+ for (StateController controller : mControllers) {
+ controller.onSystemServicesReady();
+ }
mAppStateTracker = Preconditions.checkNotNull(
LocalServices.getService(AppStateTracker.class));
@@ -3448,6 +3211,11 @@
};
synchronized (mLock) {
mConstants.dump(pw);
+ for (StateController controller : mControllers) {
+ pw.increaseIndent();
+ controller.dumpConstants(pw);
+ pw.decreaseIndent();
+ }
pw.println();
pw.println(" Heartbeat:");
@@ -3638,7 +3406,13 @@
};
synchronized (mLock) {
- mConstants.dump(proto, JobSchedulerServiceDumpProto.SETTINGS);
+ final long settingsToken = proto.start(JobSchedulerServiceDumpProto.SETTINGS);
+ mConstants.dump(proto);
+ for (StateController controller : mControllers) {
+ controller.dumpConstants(proto);
+ }
+ proto.end(settingsToken);
+
proto.write(JobSchedulerServiceDumpProto.CURRENT_HEARTBEAT, mHeartbeat);
proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[0]);
proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[1]);
diff --git a/services/core/java/com/android/server/job/controllers/QuotaController.java b/services/core/java/com/android/server/job/controllers/QuotaController.java
index 11f0939..2a9d3f3 100644
--- a/services/core/java/com/android/server/job/controllers/QuotaController.java
+++ b/services/core/java/com/android/server/job/controllers/QuotaController.java
@@ -34,9 +34,12 @@
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
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;
@@ -44,8 +47,10 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.KeyValueListParser;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -57,6 +62,7 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.job.ConstantsProto;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -354,6 +360,7 @@
private final AlarmManager mAlarmManager;
private final ChargingTracker mChargeTracker;
private final Handler mHandler;
+ private final QcConstants mQcConstants;
private volatile boolean mInParole;
@@ -489,6 +496,7 @@
mChargeTracker.startTracking();
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ mQcConstants = new QcConstants(mHandler);
final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
mContext.registerReceiverAsUser(mPackageAddedReceiver, UserHandle.ALL, filter, null, null);
@@ -506,7 +514,12 @@
// ignored; both services live in system_server
}
- onConstantsUpdatedLocked();
+ mShouldThrottle = !mConstants.USE_HEARTBEATS;
+ }
+
+ @Override
+ public void onSystemServicesReady() {
+ mQcConstants.start(mContext.getContentResolver());
}
@Override
@@ -581,89 +594,9 @@
@Override
public void onConstantsUpdatedLocked() {
- boolean changed = false;
if (mShouldThrottle == mConstants.USE_HEARTBEATS) {
mShouldThrottle = !mConstants.USE_HEARTBEATS;
- changed = true;
- }
- long newAllowedTimeMs = Math.min(MAX_PERIOD_MS,
- Math.max(MINUTE_IN_MILLIS, mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS));
- if (mAllowedTimePerPeriodMs != newAllowedTimeMs) {
- mAllowedTimePerPeriodMs = newAllowedTimeMs;
- mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
- changed = true;
- }
- long newQuotaBufferMs = Math.max(0,
- Math.min(5 * MINUTE_IN_MILLIS, mConstants.QUOTA_CONTROLLER_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, mConstants.QUOTA_CONTROLLER_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, mConstants.QUOTA_CONTROLLER_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, mConstants.QUOTA_CONTROLLER_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, mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS));
- if (mBucketPeriodsMs[RARE_INDEX] != newRarePeriodMs) {
- mBucketPeriodsMs[RARE_INDEX] = newRarePeriodMs;
- changed = true;
- }
- long newMaxExecutionTimeMs = Math.max(60 * MINUTE_IN_MILLIS,
- Math.min(MAX_PERIOD_MS, mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS));
- if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
- mMaxExecutionTimeMs = newMaxExecutionTimeMs;
- mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
- changed = true;
- }
- int newMaxCountPerAllowedPeriod = Math.max(10,
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME);
- if (mMaxJobCountPerAllowedTime != newMaxCountPerAllowedPeriod) {
- mMaxJobCountPerAllowedTime = newMaxCountPerAllowedPeriod;
- changed = true;
- }
- int newActiveMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE));
- if (mMaxBucketJobCounts[ACTIVE_INDEX] != newActiveMaxJobCount) {
- mMaxBucketJobCounts[ACTIVE_INDEX] = newActiveMaxJobCount;
- changed = true;
- }
- int newWorkingMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING));
- if (mMaxBucketJobCounts[WORKING_INDEX] != newWorkingMaxJobCount) {
- mMaxBucketJobCounts[WORKING_INDEX] = newWorkingMaxJobCount;
- changed = true;
- }
- int newFrequentMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT));
- if (mMaxBucketJobCounts[FREQUENT_INDEX] != newFrequentMaxJobCount) {
- mMaxBucketJobCounts[FREQUENT_INDEX] = newFrequentMaxJobCount;
- changed = true;
- }
- int newRareMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE));
- if (mMaxBucketJobCounts[RARE_INDEX] != newRareMaxJobCount) {
- mMaxBucketJobCounts[RARE_INDEX] = newRareMaxJobCount;
- changed = true;
- }
- if (changed) {
// Update job bookkeeping out of band.
BackgroundThread.getHandler().post(() -> {
synchronized (mLock) {
@@ -1891,6 +1824,311 @@
}
}
+ @VisibleForTesting
+ class QcConstants extends ContentObserver {
+ private ContentResolver mResolver;
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ 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_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_PER_ALLOWED_TIME =
+ "max_count_per_allowed_time";
+
+ private static final long DEFAULT_ALLOWED_TIME_PER_PERIOD_MS =
+ 10 * 60 * 1000L; // 10 minutes
+ private static final long DEFAULT_IN_QUOTA_BUFFER_MS =
+ 30 * 1000L; // 30 seconds
+ private static final long DEFAULT_WINDOW_SIZE_ACTIVE_MS =
+ 10 * 60 * 1000L; // 10 minutes for ACTIVE -- ACTIVE apps can run jobs at any time
+ private static final long DEFAULT_WINDOW_SIZE_WORKING_MS =
+ 2 * 60 * 60 * 1000L; // 2 hours
+ private static final long DEFAULT_WINDOW_SIZE_FREQUENT_MS =
+ 8 * 60 * 60 * 1000L; // 8 hours
+ private static final long DEFAULT_WINDOW_SIZE_RARE_MS =
+ 24 * 60 * 60 * 1000L; // 24 hours
+ private static final long DEFAULT_MAX_EXECUTION_TIME_MS =
+ 4 * 60 * 60 * 1000L; // 4 hours
+ private static final int DEFAULT_MAX_JOB_COUNT_ACTIVE =
+ 200; // 1200/hr
+ private static final int DEFAULT_MAX_JOB_COUNT_WORKING =
+ 1200; // 600/hr
+ private static final int DEFAULT_MAX_JOB_COUNT_FREQUENT =
+ 1800; // 225/hr
+ private static final int DEFAULT_MAX_JOB_COUNT_RARE =
+ 2400; // 100/hr
+ private static final int DEFAULT_MAX_JOB_COUNT_PER_ALLOWED_TIME = 20;
+
+ /** How much time each app will have to run jobs within their standby bucket window. */
+ public long ALLOWED_TIME_PER_PERIOD_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
+
+ /**
+ * How much time the package should have before transitioning from out-of-quota to in-quota.
+ * This should not affect processing if the package is already in-quota.
+ */
+ public long IN_QUOTA_BUFFER_MS = DEFAULT_IN_QUOTA_BUFFER_MS;
+
+ /**
+ * The quota window size of the particular standby bucket. Apps in this standby bucket are
+ * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+ * WINDOW_SIZE_MS.
+ */
+ public long WINDOW_SIZE_ACTIVE_MS = DEFAULT_WINDOW_SIZE_ACTIVE_MS;
+
+ /**
+ * The quota window size of the particular standby bucket. Apps in this standby bucket are
+ * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+ * WINDOW_SIZE_MS.
+ */
+ public long WINDOW_SIZE_WORKING_MS = DEFAULT_WINDOW_SIZE_WORKING_MS;
+
+ /**
+ * The quota window size of the particular standby bucket. Apps in this standby bucket are
+ * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+ * WINDOW_SIZE_MS.
+ */
+ public long WINDOW_SIZE_FREQUENT_MS = DEFAULT_WINDOW_SIZE_FREQUENT_MS;
+
+ /**
+ * The quota window size of the particular standby bucket. Apps in this standby bucket are
+ * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_MS} within the past
+ * WINDOW_SIZE_MS.
+ */
+ public long WINDOW_SIZE_RARE_MS = DEFAULT_WINDOW_SIZE_RARE_MS;
+
+ /**
+ * The maximum amount of time an app can have its jobs running within a 24 hour window.
+ */
+ public long MAX_EXECUTION_TIME_MS = DEFAULT_MAX_EXECUTION_TIME_MS;
+
+ /**
+ * The maximum number of jobs an app can run within this particular standby bucket's
+ * window size.
+ */
+ public int MAX_JOB_COUNT_ACTIVE = DEFAULT_MAX_JOB_COUNT_ACTIVE;
+
+ /**
+ * The maximum number of jobs an app can run within this particular standby bucket's
+ * window size.
+ */
+ public int MAX_JOB_COUNT_WORKING = DEFAULT_MAX_JOB_COUNT_WORKING;
+
+ /**
+ * The maximum number of jobs an app can run within this particular standby bucket's
+ * window size.
+ */
+ public int MAX_JOB_COUNT_FREQUENT = DEFAULT_MAX_JOB_COUNT_FREQUENT;
+
+ /**
+ * The maximum number of jobs an app can run within this particular standby bucket's
+ * window size.
+ */
+ public int MAX_JOB_COUNT_RARE = DEFAULT_MAX_JOB_COUNT_RARE;
+
+ /**
+ * The maximum number of jobs that can run within the past
+ * {@link #ALLOWED_TIME_PER_PERIOD_MS}.
+ */
+ public int MAX_JOB_COUNT_PER_ALLOWED_TIME = DEFAULT_MAX_JOB_COUNT_PER_ALLOWED_TIME;
+
+ QcConstants(Handler handler) {
+ super(handler);
+ }
+
+ private void start(ContentResolver resolver) {
+ mResolver = resolver;
+ mResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS), false, this);
+ updateConstants();
+ }
+
+ @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);
+ }
+
+ 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);
+ 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_PER_ALLOWED_TIME = mParser.getInt(
+ KEY_MAX_JOB_COUNT_PER_ALLOWED_TIME, DEFAULT_MAX_JOB_COUNT_PER_ALLOWED_TIME);
+
+ updateConstants();
+ }
+
+ @VisibleForTesting
+ void updateConstants() {
+ synchronized (mLock) {
+ boolean changed = false;
+
+ long newAllowedTimeMs = Math.min(MAX_PERIOD_MS,
+ Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_MS));
+ if (mAllowedTimePerPeriodMs != newAllowedTimeMs) {
+ mAllowedTimePerPeriodMs = newAllowedTimeMs;
+ mAllowedTimeIntoQuotaMs = mAllowedTimePerPeriodMs - mQuotaBufferMs;
+ changed = true;
+ }
+ long newQuotaBufferMs = Math.max(0,
+ 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;
+ }
+ long newMaxExecutionTimeMs = Math.max(60 * MINUTE_IN_MILLIS,
+ Math.min(MAX_PERIOD_MS, MAX_EXECUTION_TIME_MS));
+ if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
+ mMaxExecutionTimeMs = newMaxExecutionTimeMs;
+ mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
+ changed = true;
+ }
+ int newMaxCountPerAllowedPeriod = Math.max(10,
+ MAX_JOB_COUNT_PER_ALLOWED_TIME);
+ if (mMaxJobCountPerAllowedTime != newMaxCountPerAllowedPeriod) {
+ mMaxJobCountPerAllowedTime = newMaxCountPerAllowedPeriod;
+ changed = true;
+ }
+ int newActiveMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
+ 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(mMaxJobCountPerAllowedTime,
+ 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(mMaxJobCountPerAllowedTime,
+ 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(mMaxJobCountPerAllowedTime,
+ Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RARE));
+ if (mMaxBucketJobCounts[RARE_INDEX] != newRareMaxJobCount) {
+ mMaxBucketJobCounts[RARE_INDEX] = newRareMaxJobCount;
+ changed = true;
+ }
+
+ if (changed && mShouldThrottle) {
+ // Update job bookkeeping out of band.
+ BackgroundThread.getHandler().post(() -> {
+ synchronized (mLock) {
+ maybeUpdateAllConstraintsLocked();
+ }
+ });
+ }
+ }
+ }
+
+ private void dump(IndentingPrintWriter pw) {
+ pw.println();
+ pw.println("QuotaController:");
+ pw.increaseIndent();
+ pw.printPair(KEY_ALLOWED_TIME_PER_PERIOD_MS, ALLOWED_TIME_PER_PERIOD_MS).println();
+ pw.printPair(KEY_IN_QUOTA_BUFFER_MS, IN_QUOTA_BUFFER_MS).println();
+ pw.printPair(KEY_WINDOW_SIZE_ACTIVE_MS, WINDOW_SIZE_ACTIVE_MS).println();
+ pw.printPair(KEY_WINDOW_SIZE_WORKING_MS, WINDOW_SIZE_WORKING_MS).println();
+ pw.printPair(KEY_WINDOW_SIZE_FREQUENT_MS, WINDOW_SIZE_FREQUENT_MS).println();
+ pw.printPair(KEY_WINDOW_SIZE_RARE_MS, WINDOW_SIZE_RARE_MS).println();
+ pw.printPair(KEY_MAX_EXECUTION_TIME_MS, MAX_EXECUTION_TIME_MS).println();
+ pw.printPair(KEY_MAX_JOB_COUNT_ACTIVE, MAX_JOB_COUNT_ACTIVE).println();
+ pw.printPair(KEY_MAX_JOB_COUNT_WORKING, MAX_JOB_COUNT_WORKING).println();
+ pw.printPair(KEY_MAX_JOB_COUNT_FREQUENT, MAX_JOB_COUNT_FREQUENT).println();
+ pw.printPair(KEY_MAX_JOB_COUNT_RARE, MAX_JOB_COUNT_RARE).println();
+ pw.printPair(KEY_MAX_JOB_COUNT_PER_ALLOWED_TIME, MAX_JOB_COUNT_PER_ALLOWED_TIME)
+ .println();
+ pw.decreaseIndent();
+ }
+
+ private void dump(ProtoOutputStream proto) {
+ final long qcToken = proto.start(ConstantsProto.QUOTA_CONTROLLER);
+ proto.write(ConstantsProto.QuotaController.ALLOWED_TIME_PER_PERIOD_MS,
+ ALLOWED_TIME_PER_PERIOD_MS);
+ proto.write(ConstantsProto.QuotaController.IN_QUOTA_BUFFER_MS, IN_QUOTA_BUFFER_MS);
+ proto.write(ConstantsProto.QuotaController.ACTIVE_WINDOW_SIZE_MS,
+ WINDOW_SIZE_ACTIVE_MS);
+ proto.write(ConstantsProto.QuotaController.WORKING_WINDOW_SIZE_MS,
+ WINDOW_SIZE_WORKING_MS);
+ proto.write(ConstantsProto.QuotaController.FREQUENT_WINDOW_SIZE_MS,
+ WINDOW_SIZE_FREQUENT_MS);
+ proto.write(ConstantsProto.QuotaController.RARE_WINDOW_SIZE_MS, WINDOW_SIZE_RARE_MS);
+ proto.write(ConstantsProto.QuotaController.MAX_EXECUTION_TIME_MS,
+ MAX_EXECUTION_TIME_MS);
+ proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_ACTIVE, MAX_JOB_COUNT_ACTIVE);
+ proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_WORKING,
+ MAX_JOB_COUNT_WORKING);
+ proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_FREQUENT,
+ MAX_JOB_COUNT_FREQUENT);
+ proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_RARE, MAX_JOB_COUNT_RARE);
+ proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_PER_ALLOWED_TIME,
+ MAX_JOB_COUNT_PER_ALLOWED_TIME);
+ proto.end(qcToken);
+ }
+ }
+
//////////////////////// TESTING HELPERS /////////////////////////////
@VisibleForTesting
@@ -1943,6 +2181,12 @@
return mTimingSessions.get(userId, packageName);
}
+ @VisibleForTesting
+ @NonNull
+ QcConstants getQcConstants() {
+ return mQcConstants;
+ }
+
//////////////////////////// DATA DUMP //////////////////////////////
@Override
@@ -2188,4 +2432,14 @@
proto.end(mToken);
proto.end(token);
}
+
+ @Override
+ public void dumpConstants(IndentingPrintWriter pw) {
+ mQcConstants.dump(pw);
+ }
+
+ @Override
+ public void dumpConstants(ProtoOutputStream proto) {
+ mQcConstants.dump(proto);
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 74628fb..51be38b 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -52,6 +52,13 @@
}
/**
+ * Called when the system boot phase has reached
+ * {@link com.android.server.SystemService#PHASE_SYSTEM_SERVICES_READY}.
+ */
+ public void onSystemServicesReady() {
+ }
+
+ /**
* Implement the logic here to decide whether a job should be tracked by this controller.
* This logic is put here so the JobManager can be completely agnostic of Controller logic.
* Also called when updating a task, so implementing controllers have to be aware of
@@ -127,4 +134,12 @@
Predicate<JobStatus> predicate);
public abstract void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
Predicate<JobStatus> predicate);
+
+ /** Dump any internal constants the Controller may have. */
+ public void dumpConstants(IndentingPrintWriter pw) {
+ }
+
+ /** Dump any internal constants the Controller may have. */
+ public void dumpConstants(ProtoOutputStream proto) {
+ }
}
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index 70deb38..ababad9 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -18,13 +18,20 @@
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.AlarmManager.OnAlarmListener;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
import android.util.Log;
import android.util.Slog;
import android.util.TimeUtils;
@@ -32,6 +39,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.job.ConstantsProto;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -55,6 +63,9 @@
/** Delay alarm tag for logging purposes */
private final String DELAY_TAG = "*job.delay*";
+ private final Handler mHandler;
+ private final TcConstants mTcConstants;
+
private long mNextJobExpiredElapsedMillis;
private long mNextDelayExpiredElapsedMillis;
@@ -70,6 +81,14 @@
mNextJobExpiredElapsedMillis = Long.MAX_VALUE;
mNextDelayExpiredElapsedMillis = Long.MAX_VALUE;
mChainedAttributionEnabled = mService.isChainedAttributionEnabled();
+
+ mHandler = new Handler(mContext.getMainLooper());
+ mTcConstants = new TcConstants(mHandler);
+ }
+
+ @Override
+ public void onSystemServicesReady() {
+ mTcConstants.start(mContext.getContentResolver());
}
/**
@@ -118,7 +137,7 @@
job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE;
final long delayExpiredElapsed =
job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE;
- if (mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS) {
+ if (mTcConstants.SKIP_NOT_READY_JOBS) {
if (wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
maybeUpdateDelayAlarmLocked(delayExpiredElapsed, ws);
}
@@ -148,14 +167,8 @@
}
@Override
- public void onConstantsUpdatedLocked() {
- checkExpiredDeadlinesAndResetAlarm();
- checkExpiredDelaysAndResetAlarm();
- }
-
- @Override
public void evaluateStateLocked(JobStatus job) {
- if (!mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS) {
+ if (!mTcConstants.SKIP_NOT_READY_JOBS) {
return;
}
@@ -248,7 +261,7 @@
}
it.remove();
} else { // Sorted by expiry time, so take the next one and stop.
- if (mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS
+ if (mTcConstants.SKIP_NOT_READY_JOBS
&& !wouldBeReadyWithConstraintLocked(
job, JobStatus.CONSTRAINT_DEADLINE)) {
if (DEBUG) {
@@ -308,7 +321,7 @@
ready = true;
}
} else {
- if (mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS
+ if (mTcConstants.SKIP_NOT_READY_JOBS
&& !wouldBeReadyWithConstraintLocked(
job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
if (DEBUG) {
@@ -439,6 +452,87 @@
}
};
+ @VisibleForTesting
+ void recheckAlarmsLocked() {
+ checkExpiredDeadlinesAndResetAlarm();
+ checkExpiredDelaysAndResetAlarm();
+ }
+
+ @VisibleForTesting
+ class TcConstants extends ContentObserver {
+ private ContentResolver mResolver;
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ private static final String KEY_SKIP_NOT_READY_JOBS = "skip_not_ready_jobs";
+
+ private static final boolean DEFAULT_SKIP_NOT_READY_JOBS = true;
+
+ /**
+ * Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
+ * ready now.
+ */
+ public boolean SKIP_NOT_READY_JOBS = DEFAULT_SKIP_NOT_READY_JOBS;
+
+ /**
+ * Creates a content observer.
+ *
+ * @param handler The handler to run {@link #onChange} on, or null if none.
+ */
+ TcConstants(Handler handler) {
+ super(handler);
+ }
+
+ private void start(ContentResolver resolver) {
+ mResolver = resolver;
+ mResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS), false, this);
+ onChange(true, null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ final String constants = Settings.Global.getString(
+ mResolver, Settings.Global.JOB_SCHEDULER_TIME_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 time controller settings", e);
+ }
+
+ final boolean oldVal = SKIP_NOT_READY_JOBS;
+ SKIP_NOT_READY_JOBS = mParser.getBoolean(
+ KEY_SKIP_NOT_READY_JOBS, DEFAULT_SKIP_NOT_READY_JOBS);
+
+ if (oldVal != SKIP_NOT_READY_JOBS) {
+ synchronized (mLock) {
+ recheckAlarmsLocked();
+ }
+ }
+ }
+
+ private void dump(IndentingPrintWriter pw) {
+ pw.println();
+ pw.println("TimeController:");
+ pw.increaseIndent();
+ pw.printPair(KEY_SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS).println();
+ pw.decreaseIndent();
+ }
+
+ private void dump(ProtoOutputStream proto) {
+ final long tcToken = proto.start(ConstantsProto.TIME_CONTROLLER);
+ proto.write(ConstantsProto.TimeController.SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS);
+ proto.end(tcToken);
+ }
+ }
+
+ @VisibleForTesting
+ @NonNull
+ TcConstants getTcConstants() {
+ return mTcConstants;
+ }
+
@Override
public void dumpControllerStateLocked(IndentingPrintWriter pw,
Predicate<JobStatus> predicate) {
@@ -513,4 +607,14 @@
proto.end(mToken);
proto.end(token);
}
+
+ @Override
+ public void dumpConstants(IndentingPrintWriter pw) {
+ mTcConstants.dump(pw);
+ }
+
+ @Override
+ public void dumpConstants(ProtoOutputStream proto) {
+ mTcConstants.dump(proto);
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 7c30f25..2e7283c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -105,8 +105,9 @@
private static final int SOURCE_USER_ID = 0;
private BroadcastReceiver mChargingReceiver;
- private Constants mConstants;
+ private Constants mJsConstants;
private QuotaController mQuotaController;
+ private QuotaController.QcConstants mQcConstants;
private int mSourceUid;
private IUidObserver mUidObserver;
@@ -132,13 +133,13 @@
.mockStatic(LocalServices.class)
.startMocking();
// Make sure constants turn on QuotaController.
- mConstants = new Constants();
- mConstants.USE_HEARTBEATS = false;
+ mJsConstants = new Constants();
+ mJsConstants.USE_HEARTBEATS = false;
// Called in StateController constructor.
when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
- when(mJobSchedulerService.getConstants()).thenReturn(mConstants);
+ when(mJobSchedulerService.getConstants()).thenReturn(mJsConstants);
// Called in QuotaController constructor.
IActivityManager activityManager = ActivityManager.getService();
spyOn(activityManager);
@@ -196,6 +197,7 @@
} catch (RemoteException e) {
fail(e.getMessage());
}
+ mQcConstants = mQuotaController.getQcConstants();
}
@After
@@ -531,7 +533,7 @@
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -544,7 +546,7 @@
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -557,7 +559,7 @@
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -574,7 +576,7 @@
expectedStats.executionTimeInMaxPeriodMs = 23 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 18;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -590,7 +592,7 @@
expectedStats.executionTimeInMaxPeriodMs = 24 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
}
@@ -630,7 +632,7 @@
expectedStats.executionTimeInMaxPeriodMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - 3 * MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
assertEquals(expectedStats,
mQuotaController.getExecutionStatsLocked(0, "com.android.test", WORKING_INDEX));
@@ -642,7 +644,7 @@
expectedStats.executionTimeInMaxPeriodMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - 3 * MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
assertEquals(expectedStats,
mQuotaController.getExecutionStatsLocked(0, "com.android.test", FREQUENT_INDEX));
@@ -654,7 +656,7 @@
expectedStats.executionTimeInMaxPeriodMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - 3 * MINUTE_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
assertEquals(expectedStats,
mQuotaController.getExecutionStatsLocked(0, "com.android.test", RARE_INDEX));
}
@@ -685,8 +687,8 @@
// 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.
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS = 6 * HOUR_IN_MILLIS;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.WINDOW_SIZE_FREQUENT_MS = 6 * HOUR_IN_MILLIS;
+ mQcConstants.updateConstants();
ExecutionStats expectedStats = new ExecutionStats();
expectedStats.windowSizeMs = originalStatsActive.windowSizeMs;
@@ -778,7 +780,7 @@
setStandbyBucket(ACTIVE_INDEX);
assertEquals(7 * MINUTE_IN_MILLIS,
mQuotaController.getRemainingExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
- assertEquals(mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS - 9 * MINUTE_IN_MILLIS,
+ assertEquals(mQcConstants.MAX_EXECUTION_TIME_MS - 9 * MINUTE_IN_MILLIS,
mQuotaController.getTimeUntilQuotaConsumedLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
}
@@ -901,7 +903,7 @@
public void testIsWithinQuotaLocked_UnderDuration_OverJobCount() {
setDischarging();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
- final int jobCount = mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME;
+ final int jobCount = mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME;
mQuotaController.saveTimingSession(0, "com.android.test.spam",
createTimingSession(now - (HOUR_IN_MILLIS), 15 * MINUTE_IN_MILLIS, 25));
mQuotaController.saveTimingSession(0, "com.android.test.spam",
@@ -936,7 +938,7 @@
public void testIsWithinQuotaLocked_OverDuration_OverJobCount() {
setDischarging();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
- final int jobCount = mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME;
+ final int jobCount = mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME;
mQuotaController.saveTimingSession(0, "com.android.test",
createTimingSession(now - (HOUR_IN_MILLIS), 15 * MINUTE_IN_MILLIS, 25));
mQuotaController.saveTimingSession(0, "com.android.test",
@@ -1098,8 +1100,7 @@
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
// Test with timing sessions out of window but still under max execution limit.
final long expectedAlarmTime =
- (now - 18 * HOUR_IN_MILLIS) + 24 * HOUR_IN_MILLIS
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ (now - 18 * HOUR_IN_MILLIS) + 24 * HOUR_IN_MILLIS + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
createTimingSession(now - 18 * HOUR_IN_MILLIS, HOUR_IN_MILLIS, 1));
mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
@@ -1156,8 +1157,7 @@
final long end = now - (2 * HOUR_IN_MILLIS - 5 * MINUTE_IN_MILLIS);
// Counting backwards, the quota will come back one minute before the end.
final long expectedAlarmTime =
- end - MINUTE_IN_MILLIS + 2 * HOUR_IN_MILLIS
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ end - MINUTE_IN_MILLIS + 2 * HOUR_IN_MILLIS + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.saveTimingSession(0, "com.android.test",
new TimingSession(now - 2 * HOUR_IN_MILLIS, end, 1));
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", standbyBucket);
@@ -1207,8 +1207,7 @@
// Test with timing sessions in window but still in quota.
final long start = now - (6 * HOUR_IN_MILLIS);
- final long expectedAlarmTime =
- start + 8 * HOUR_IN_MILLIS + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ final long expectedAlarmTime = start + 8 * HOUR_IN_MILLIS + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.saveTimingSession(0, "com.android.test",
createTimingSession(start, 5 * MINUTE_IN_MILLIS, 1));
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", standbyBucket);
@@ -1262,7 +1261,7 @@
// needs to be excluded.
final long expectedAlarmTime =
start + MINUTE_IN_MILLIS + 24 * HOUR_IN_MILLIS
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.saveTimingSession(0, "com.android.test",
createTimingSession(start, 5 * MINUTE_IN_MILLIS, 1));
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", standbyBucket);
@@ -1324,21 +1323,21 @@
// And down from there.
final long expectedWorkingAlarmTime =
outOfQuotaTime + (2 * HOUR_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", WORKING_INDEX);
inOrder.verify(mAlarmManager, times(1))
.set(anyInt(), eq(expectedWorkingAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
final long expectedFrequentAlarmTime =
outOfQuotaTime + (8 * HOUR_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", FREQUENT_INDEX);
inOrder.verify(mAlarmManager, times(1))
.set(anyInt(), eq(expectedFrequentAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
final long expectedRareAlarmTime =
outOfQuotaTime + (24 * HOUR_IN_MILLIS)
- + mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS;
+ + mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.maybeScheduleStartAlarmLocked(0, "com.android.test", RARE_INDEX);
inOrder.verify(mAlarmManager, times(1))
.set(anyInt(), eq(expectedRareAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
@@ -1365,7 +1364,7 @@
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
stats.jobCountInAllowedTime =
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME + 2;
+ mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME + 2;
// Invalid time in the past, so the count shouldn't be used.
stats.jobCountExpirationTimeElapsed =
@@ -1400,8 +1399,8 @@
@Test
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedBufferSize() {
// Make sure any new value is used correctly.
- mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS *= 2;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.IN_QUOTA_BUFFER_MS *= 2;
+ mQcConstants.updateConstants();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
@@ -1410,8 +1409,8 @@
@Test
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedAllowedTime() {
// Make sure any new value is used correctly.
- mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS /= 2;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.ALLOWED_TIME_PER_PERIOD_MS /= 2;
+ mQcConstants.updateConstants();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
@@ -1420,8 +1419,8 @@
@Test
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedMaxTime() {
// Make sure any new value is used correctly.
- mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS /= 2;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.MAX_EXECUTION_TIME_MS /= 2;
+ mQcConstants.updateConstants();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
@@ -1430,10 +1429,10 @@
@Test
public void testMaybeScheduleStartAlarmLocked_SmallRollingQuota_UpdatedEverything() {
// Make sure any new value is used correctly.
- mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS *= 2;
- mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS /= 2;
- mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS /= 2;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.IN_QUOTA_BUFFER_MS *= 2;
+ mQcConstants.ALLOWED_TIME_PER_PERIOD_MS /= 2;
+ mQcConstants.MAX_EXECUTION_TIME_MS /= 2;
+ mQcConstants.updateConstants();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_AllowedTimeCheck();
mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE).clear();
runTestMaybeScheduleStartAlarmLocked_SmallRollingQuota_MaxTimeCheck();
@@ -1448,9 +1447,8 @@
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
// Working set window size is 2 hours.
final int standbyBucket = WORKING_INDEX;
- final long contributionMs = mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS / 2;
- final long remainingTimeMs =
- mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS - contributionMs;
+ final long contributionMs = mQcConstants.IN_QUOTA_BUFFER_MS / 2;
+ final long remainingTimeMs = mQcConstants.ALLOWED_TIME_PER_PERIOD_MS - contributionMs;
// Session straddles edge of bucket window. Only the contribution should be counted towards
// the quota.
@@ -1462,7 +1460,7 @@
// Expected alarm time should be when the app will have QUOTA_BUFFER_MS time of quota, which
// is 2 hours + (QUOTA_BUFFER_MS - contributionMs) after the start of the second session.
final long expectedAlarmTime = now - HOUR_IN_MILLIS + 2 * HOUR_IN_MILLIS
- + (mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS - contributionMs);
+ + (mQcConstants.IN_QUOTA_BUFFER_MS - contributionMs);
mQuotaController.maybeScheduleStartAlarmLocked(SOURCE_USER_ID, SOURCE_PACKAGE,
standbyBucket);
verify(mAlarmManager, times(1))
@@ -1479,9 +1477,8 @@
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
// Working set window size is 2 hours.
final int standbyBucket = WORKING_INDEX;
- final long contributionMs = mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS / 2;
- final long remainingTimeMs =
- mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS - contributionMs;
+ final long contributionMs = mQcConstants.IN_QUOTA_BUFFER_MS / 2;
+ final long remainingTimeMs = mQcConstants.MAX_EXECUTION_TIME_MS - contributionMs;
// Session straddles edge of 24 hour window. Only the contribution should be counted towards
// the quota.
@@ -1493,9 +1490,8 @@
// Expected alarm time should be when the app will have QUOTA_BUFFER_MS time of quota, which
// is 24 hours + (QUOTA_BUFFER_MS - contributionMs) after the start of the second session.
final long expectedAlarmTime = now - 20 * HOUR_IN_MILLIS
- //+ mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS
+ 24 * HOUR_IN_MILLIS
- + (mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS - contributionMs);
+ + (mQcConstants.IN_QUOTA_BUFFER_MS - contributionMs);
mQuotaController.maybeScheduleStartAlarmLocked(SOURCE_USER_ID, SOURCE_PACKAGE,
standbyBucket);
verify(mAlarmManager, times(1))
@@ -1515,12 +1511,12 @@
mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
assertFalse(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
- mConstants.USE_HEARTBEATS = true;
+ mJsConstants.USE_HEARTBEATS = true;
mQuotaController.onConstantsUpdatedLocked();
Thread.sleep(SECOND_IN_MILLIS); // Job updates are done in the background.
assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
- mConstants.USE_HEARTBEATS = false;
+ mJsConstants.USE_HEARTBEATS = false;
mQuotaController.onConstantsUpdatedLocked();
Thread.sleep(SECOND_IN_MILLIS); // Job updates are done in the background.
assertFalse(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
@@ -1528,20 +1524,20 @@
@Test
public void testConstantsUpdating_ValidValues() {
- mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS = 5 * MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS = 2 * MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS = 15 * MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS = 30 * MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS = 45 * MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS = 60 * MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS = 3 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE = 5000;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING = 4000;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT = 3000;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE = 2000;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME = 500;
+ 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.MAX_JOB_COUNT_PER_ALLOWED_TIME = 500;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.updateConstants();
assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
assertEquals(2 * MINUTE_IN_MILLIS, mQuotaController.getInQuotaBufferMs());
@@ -1561,20 +1557,20 @@
@Test
public void testConstantsUpdating_InvalidValues() {
// Test negatives/too low.
- mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS = -MINUTE_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_ACTIVE = -1;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_WORKING = 1;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_FREQUENT = 1;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_RARE = 1;
- mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME = 0;
+ 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.MAX_JOB_COUNT_PER_ALLOWED_TIME = 0;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.updateConstants();
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
assertEquals(0, mQuotaController.getInQuotaBufferMs());
@@ -1590,15 +1586,15 @@
assertEquals(100, mQuotaController.getBucketMaxJobCounts()[RARE_INDEX]);
// Test larger than a day. Controller should cap at one day.
- mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS = 25 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_IN_QUOTA_BUFFER_MS = 25 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_ACTIVE_MS = 25 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_WORKING_MS = 25 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_FREQUENT_MS = 25 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_WINDOW_SIZE_RARE_MS = 25 * HOUR_IN_MILLIS;
- mConstants.QUOTA_CONTROLLER_MAX_EXECUTION_TIME_MS = 25 * HOUR_IN_MILLIS;
+ 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;
- mQuotaController.onConstantsUpdatedLocked();
+ mQcConstants.updateConstants();
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getAllowedTimePerPeriodMs());
assertEquals(5 * MINUTE_IN_MILLIS, mQuotaController.getInQuotaBufferMs());
@@ -2219,7 +2215,7 @@
verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
// Ran jobs up to the job limit. All of them should be allowed to run.
- for (int i = 0; i < mConstants.QUOTA_CONTROLLER_MAX_JOB_COUNT_PER_ALLOWED_TIME; ++i) {
+ for (int i = 0; i < mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME; ++i) {
JobStatus job = createJobStatus("testStartAlarmScheduled_JobCount_AllowedTime", i);
mQuotaController.maybeStartTrackingJobLocked(job, null);
assertTrue(job.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
@@ -2240,7 +2236,7 @@
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
final long expectedWorkingAlarmTime =
- stats.jobCountExpirationTimeElapsed + mConstants.QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS;
+ stats.jobCountExpirationTimeElapsed + mQcConstants.ALLOWED_TIME_PER_PERIOD_MS;
verify(mAlarmManager, times(1))
.set(anyInt(), eq(expectedWorkingAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
index 494677d..19369db 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
@@ -39,6 +39,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
+import android.os.Looper;
import android.os.SystemClock;
import androidx.test.runner.AndroidJUnit4;
@@ -70,7 +71,7 @@
private static final String SOURCE_PACKAGE = "com.android.frameworks.mockingservicestests";
private static final int SOURCE_USER_ID = 0;
- private Constants mConstants;
+ private TimeController.TcConstants mConstants;
private TimeController mTimeController;
private MockitoSession mMockingSession;
@@ -88,14 +89,13 @@
.strictness(Strictness.LENIENT)
.mockStatic(LocalServices.class)
.startMocking();
- // Use default constants for now.
- mConstants = new Constants();
// Called in StateController constructor.
when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
- when(mJobSchedulerService.getConstants()).thenReturn(mConstants);
+ when(mJobSchedulerService.getConstants()).thenReturn(mock(Constants.class));
// Called in TimeController constructor.
+ when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
// Used in JobStatus.
doReturn(mock(PackageManagerInternal.class))
@@ -111,6 +111,7 @@
// Initialize real objects.
mTimeController = new TimeController(mJobSchedulerService);
+ mConstants = mTimeController.getTcConstants();
spyOn(mTimeController);
}
@@ -159,7 +160,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DelayInOrder_NoSkipping() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
+ mConstants.SKIP_NOT_READY_JOBS = false;
mTimeController.onConstantsUpdatedLocked();
runTestMaybeStartTrackingJobLocked_DelayInOrder();
@@ -167,7 +168,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DelayInOrder_WithSkipping_AllReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
@@ -201,7 +202,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DelayInOrder_WithSkipping_SomeNotReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -235,7 +236,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DelayReverseOrder_NoSkipping() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
+ mConstants.SKIP_NOT_READY_JOBS = false;
mTimeController.onConstantsUpdatedLocked();
runTestMaybeStartTrackingJobLocked_DelayReverseOrder();
@@ -243,7 +244,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DelayReverseOrder_WithSkipping_AllReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
@@ -279,7 +280,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DelayReverseOrder_WithSkipping_SomeNotReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -315,7 +316,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DeadlineInOrder_NoSkipping() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
+ mConstants.SKIP_NOT_READY_JOBS = false;
mTimeController.onConstantsUpdatedLocked();
runTestMaybeStartTrackingJobLocked_DeadlineInOrder();
@@ -323,7 +324,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DeadlineInOrder_WithSkipping_AllReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
@@ -357,7 +358,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DeadlineInOrder_WithSkipping_SomeNotReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -391,7 +392,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_NoSkipping() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
+ mConstants.SKIP_NOT_READY_JOBS = false;
mTimeController.onConstantsUpdatedLocked();
runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder();
@@ -399,7 +400,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_WithSkipping_AllReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
@@ -438,7 +439,7 @@
@Test
public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_WithSkipping_SomeNotReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
+ mConstants.SKIP_NOT_READY_JOBS = true;
mTimeController.onConstantsUpdatedLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
@@ -493,8 +494,8 @@
.wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
// Starting off with the skipping off, we should still set an alarm for the earlier job.
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = false;
+ mTimeController.recheckAlarmsLocked();
InOrder inOrder = inOrder(mAlarmManager);
mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
@@ -504,16 +505,16 @@
eq(TAG_DEADLINE), any(), any(), any());
// Turn it on, use alarm for later job.
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
inOrder.verify(mAlarmManager, times(1))
.set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
any(), any(), any());
// Back off, use alarm for earlier job.
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = false;
+ mTimeController.recheckAlarmsLocked();
inOrder.verify(mAlarmManager, times(1))
.set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
@@ -522,16 +523,16 @@
@Test
public void testCheckExpiredDelaysAndResetAlarm_NoSkipping() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = false;
+ mTimeController.recheckAlarmsLocked();
runTestCheckExpiredDelaysAndResetAlarm();
}
@Test
public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_AllReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
@@ -589,8 +590,8 @@
@Test
public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_SomeNotReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
JobStatus jobLatest = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
@@ -639,16 +640,16 @@
@Test
public void testCheckExpiredDeadlinesAndResetAlarm_NoSkipping() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = false;
+ mTimeController.recheckAlarmsLocked();
runTestCheckExpiredDeadlinesAndResetAlarm();
}
@Test
public void testCheckExpiredDeadlinesAndResetAlarm_WithSkipping_AllReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
@@ -706,8 +707,8 @@
@Test
public void testCheckExpiredDeadlinesAndResetAlarm_WithSkipping_SomeNotReady() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
JobStatus jobLatest = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
@@ -756,8 +757,8 @@
@Test
public void testEvaluateStateLocked_SkippingOff() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = false;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = false;
+ mTimeController.recheckAlarmsLocked();
JobStatus job = createJobStatus("testEvaluateStateLocked_SkippingOff",
createJob().setOverrideDeadline(HOUR_IN_MILLIS));
@@ -768,8 +769,8 @@
@Test
public void testEvaluateStateLocked_SkippingOn_Delay() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
@@ -827,8 +828,8 @@
@Test
public void testEvaluateStateLocked_SkippingOn_Deadline() {
- mConstants.TIME_CONTROLLER_SKIP_NOT_READY_JOBS = true;
- mTimeController.onConstantsUpdatedLocked();
+ mConstants.SKIP_NOT_READY_JOBS = true;
+ mTimeController.recheckAlarmsLocked();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",