summaryrefslogtreecommitdiff
path: root/apex
diff options
context:
space:
mode:
Diffstat (limited to 'apex')
-rw-r--r--apex/jobscheduler/framework/aconfig/job.aconfig8
-rw-r--r--apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java12
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl2
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobScheduler.java28
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.aidl19
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.java100
-rw-r--r--apex/jobscheduler/service/aconfig/alarm.aconfig10
-rw-r--r--apex/jobscheduler/service/aconfig/app_idle.aconfig7
-rw-r--r--apex/jobscheduler/service/aconfig/device_idle.aconfig10
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java32
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java87
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java51
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java96
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java53
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java58
16 files changed, 460 insertions, 116 deletions
diff --git a/apex/jobscheduler/framework/aconfig/job.aconfig b/apex/jobscheduler/framework/aconfig/job.aconfig
index 79aef1e6a19a..47a85498f51b 100644
--- a/apex/jobscheduler/framework/aconfig/job.aconfig
+++ b/apex/jobscheduler/framework/aconfig/job.aconfig
@@ -45,3 +45,11 @@ flag {
description: "Introduce a new getPendingJobReasons() API which returns reasons why a job may not have executed. Also deprecate the existing getPendingJobReason() API."
bug: "372031023"
}
+
+flag {
+ name: "get_pending_job_reasons_history_api"
+ is_exported: true
+ namespace: "backstage_power"
+ description: "Introduce a new getPendingJobReasonsHistory() API which returns a limited historical view of getPendingJobReasons()."
+ bug: "372031023"
+}
diff --git a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
index fb5ef8771c26..e9b11f46ddde 100644
--- a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
+++ b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
@@ -25,11 +25,13 @@ import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.job.JobSnapshot;
import android.app.job.JobWorkItem;
+import android.app.job.PendingJobReasonsInfo;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
import android.util.ArrayMap;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -183,6 +185,16 @@ public class JobSchedulerImpl extends JobScheduler {
}
@Override
+ @NonNull
+ public List<PendingJobReasonsInfo> getPendingJobReasonsHistory(int jobId) {
+ try {
+ return mBinder.getPendingJobReasonsHistory(mNamespace, jobId);
+ } catch (RemoteException e) {
+ return Collections.EMPTY_LIST;
+ }
+ }
+
+ @Override
public boolean canRunUserInitiatedJobs() {
try {
return mBinder.canRunUserInitiatedJobs(mContext.getOpPackageName());
diff --git a/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
index 21051b520d84..dc7f3d143e4c 100644
--- a/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
+++ b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
@@ -20,6 +20,7 @@ import android.app.job.IUserVisibleJobObserver;
import android.app.job.JobInfo;
import android.app.job.JobSnapshot;
import android.app.job.JobWorkItem;
+import android.app.job.PendingJobReasonsInfo;
import android.content.pm.ParceledListSlice;
import java.util.Map;
@@ -40,6 +41,7 @@ interface IJobScheduler {
JobInfo getPendingJob(String namespace, int jobId);
int getPendingJobReason(String namespace, int jobId);
int[] getPendingJobReasons(String namespace, int jobId);
+ List<PendingJobReasonsInfo> getPendingJobReasonsHistory(String namespace, int jobId);
boolean canRunUserInitiatedJobs(String packageName);
boolean hasRunUserInitiatedJobsPermission(String packageName, int userId);
List<JobInfo> getStartedJobs();
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index bfdd15e9b0cd..4fbd55a5d528 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -493,6 +493,34 @@ public abstract class JobScheduler {
}
/**
+ * For the given {@code jobId}, returns a limited historical view of why the job may have
+ * been pending execution. The returned list is composed of {@link PendingJobReasonsInfo}
+ * objects, each of which include a timestamp since epoch along with an array of
+ * unsatisfied constraints represented by {@link PendingJobReason PendingJobReason constants}.
+ * <p>
+ * These constants could either be explicitly set constraints on the job or implicit
+ * constraints imposed by the system due to various reasons.
+ * The results can be used to debug why a given job may have been pending execution.
+ * <p>
+ * If the only {@link PendingJobReason} for the timestamp is
+ * {@link PendingJobReason#PENDING_JOB_REASON_UNDEFINED}, it could mean that
+ * the job was ready to be executed at that point in time.
+ * <p>
+ * Note: there is no set interval for the timestamps in the returned list since
+ * constraint changes occur based on device status and various other factors.
+ * <p>
+ * Note: the pending job reasons history is not persisted across device reboots.
+ * <p>
+ * @throws IllegalArgumentException if the {@code jobId} is invalid.
+ * @see #getPendingJobReasons(int)
+ */
+ @FlaggedApi(Flags.FLAG_GET_PENDING_JOB_REASONS_HISTORY_API)
+ @NonNull
+ public List<PendingJobReasonsInfo> getPendingJobReasonsHistory(int jobId) {
+ throw new UnsupportedOperationException("Not implemented by " + getClass());
+ }
+
+ /**
* Returns {@code true} if the calling app currently holds the
* {@link android.Manifest.permission#RUN_USER_INITIATED_JOBS} permission, allowing it to run
* user-initiated jobs.
diff --git a/apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.aidl b/apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.aidl
new file mode 100644
index 000000000000..1a027020e25f
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ package android.app.job;
+
+ parcelable PendingJobReasonsInfo;
diff --git a/apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.java b/apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.java
new file mode 100644
index 000000000000..3c96bab80794
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/PendingJobReasonsInfo.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A simple wrapper which includes a timestamp (in millis since epoch)
+ * and an array of {@link JobScheduler.PendingJobReason reasons} at that timestamp
+ * for why a particular job may be pending.
+ */
+@FlaggedApi(Flags.FLAG_GET_PENDING_JOB_REASONS_HISTORY_API)
+public final class PendingJobReasonsInfo implements Parcelable {
+
+ @CurrentTimeMillisLong
+ private final long mTimestampMillis;
+
+ @NonNull
+ @JobScheduler.PendingJobReason
+ private final int[] mPendingJobReasons;
+
+ public PendingJobReasonsInfo(long timestampMillis,
+ @NonNull @JobScheduler.PendingJobReason int[] reasons) {
+ mTimestampMillis = timestampMillis;
+ mPendingJobReasons = reasons;
+ }
+
+ /**
+ * @return the time (in millis since epoch) associated with the set of pending job reasons.
+ */
+ @CurrentTimeMillisLong
+ public long getTimestampMillis() {
+ return mTimestampMillis;
+ }
+
+ /**
+ * Returns a set of {@link android.app.job.JobScheduler.PendingJobReason reasons} representing
+ * why the job may not have executed at the associated timestamp.
+ * <p>
+ * These reasons could either be explicitly set constraints on the job or implicit
+ * constraints imposed by the system due to various reasons.
+ * <p>
+ * Note: if the only {@link android.app.job.JobScheduler.PendingJobReason} present is
+ * {@link JobScheduler.PendingJobReason#PENDING_JOB_REASON_UNDEFINED}, it could mean
+ * that the job was ready to be executed at that time.
+ */
+ @NonNull
+ @JobScheduler.PendingJobReason
+ public int[] getPendingJobReasons() {
+ return mPendingJobReasons;
+ }
+
+ private PendingJobReasonsInfo(Parcel in) {
+ mTimestampMillis = in.readLong();
+ mPendingJobReasons = in.createIntArray();
+ }
+
+ @NonNull
+ public static final Creator<PendingJobReasonsInfo> CREATOR =
+ new Creator<>() {
+ @Override
+ public PendingJobReasonsInfo createFromParcel(Parcel in) {
+ return new PendingJobReasonsInfo(in);
+ }
+
+ @Override
+ public PendingJobReasonsInfo[] newArray(int size) {
+ return new PendingJobReasonsInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeLong(mTimestampMillis);
+ dest.writeIntArray(mPendingJobReasons);
+ }
+}
diff --git a/apex/jobscheduler/service/aconfig/alarm.aconfig b/apex/jobscheduler/service/aconfig/alarm.aconfig
index d3068d7d37e8..a6e980726a9a 100644
--- a/apex/jobscheduler/service/aconfig/alarm.aconfig
+++ b/apex/jobscheduler/service/aconfig/alarm.aconfig
@@ -2,16 +2,6 @@ package: "com.android.server.alarm"
container: "system"
flag {
- name: "use_frozen_state_to_drop_listener_alarms"
- namespace: "backstage_power"
- description: "Use frozen state callback to drop listener alarms for cached apps"
- bug: "324470945"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "start_user_before_scheduled_alarms"
namespace: "multiuser"
description: "Persist list of users with alarms scheduled and wakeup stopped users before alarms are due"
diff --git a/apex/jobscheduler/service/aconfig/app_idle.aconfig b/apex/jobscheduler/service/aconfig/app_idle.aconfig
index f079c02707e0..74d2a590086f 100644
--- a/apex/jobscheduler/service/aconfig/app_idle.aconfig
+++ b/apex/jobscheduler/service/aconfig/app_idle.aconfig
@@ -21,3 +21,10 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "adjust_default_bucket_elevation_params"
+ namespace: "backstage_power"
+ description: "Adjust the default bucket evaluation parameters"
+ bug: "379909479"
+}
diff --git a/apex/jobscheduler/service/aconfig/device_idle.aconfig b/apex/jobscheduler/service/aconfig/device_idle.aconfig
index c4d0d1850a18..426031fbeb9c 100644
--- a/apex/jobscheduler/service/aconfig/device_idle.aconfig
+++ b/apex/jobscheduler/service/aconfig/device_idle.aconfig
@@ -17,3 +17,13 @@ flag {
description: "Disable wakelocks for background apps while Light Device Idle is active"
bug: "326607666"
}
+
+flag {
+ name: "use_cpu_time_for_temp_allowlist"
+ namespace: "backstage_power"
+ description: "Use CPU time for temporary allowlists"
+ bug: "376561328"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 3e650da2e66f..41fd4a29cfd1 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -620,8 +620,8 @@ public class DeviceIdleController extends SystemService
* the network and acquire wakelocks. Times are in milliseconds.
*/
@GuardedBy("this")
- private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
- = new SparseArray<>();
+ @VisibleForTesting
+ final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes = new SparseArray<>();
private NetworkPolicyManagerInternal mNetworkPolicyManagerInternal;
@@ -1941,7 +1941,8 @@ public class DeviceIdleController extends SystemService
private static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
private static final int MSG_REPORT_IDLE_OFF = 4;
private static final int MSG_REPORT_ACTIVE = 5;
- private static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
+ @VisibleForTesting
+ static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
@VisibleForTesting
static final int MSG_REPORT_STATIONARY_STATUS = 7;
private static final int MSG_FINISH_IDLE_OP = 8;
@@ -2511,6 +2512,11 @@ public class DeviceIdleController extends SystemService
return SystemClock.elapsedRealtime();
}
+ /** Returns the current elapsed realtime in milliseconds. */
+ long getUptimeMillis() {
+ return SystemClock.uptimeMillis();
+ }
+
LocationManager getLocationManager() {
if (mLocationManager == null) {
mLocationManager = mContext.getSystemService(LocationManager.class);
@@ -3264,7 +3270,8 @@ public class DeviceIdleController extends SystemService
void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int uid,
long duration, @TempAllowListType int tempAllowListType, boolean sync,
@ReasonCode int reasonCode, @Nullable String reason) {
- final long timeNow = SystemClock.elapsedRealtime();
+ final long timeNow = Flags.useCpuTimeForTempAllowlist() ? mInjector.getUptimeMillis()
+ : mInjector.getElapsedRealtime();
boolean informWhitelistChanged = false;
int appId = UserHandle.getAppId(uid);
synchronized (this) {
@@ -3350,7 +3357,8 @@ public class DeviceIdleController extends SystemService
}
void checkTempAppWhitelistTimeout(int uid) {
- final long timeNow = SystemClock.elapsedRealtime();
+ final long timeNow = Flags.useCpuTimeForTempAllowlist() ? mInjector.getUptimeMillis()
+ : mInjector.getElapsedRealtime();
final int appId = UserHandle.getAppId(uid);
if (DEBUG) {
Slog.d(TAG, "checkTempAppWhitelistTimeout: uid=" + uid + ", timeNow=" + timeNow);
@@ -5219,6 +5227,17 @@ public class DeviceIdleController extends SystemService
}
}
+ pw.println(" Flags:");
+ pw.print(" ");
+ pw.print(Flags.FLAG_USE_CPU_TIME_FOR_TEMP_ALLOWLIST);
+ pw.print("=");
+ pw.println(Flags.useCpuTimeForTempAllowlist());
+ pw.print(" ");
+ pw.print(Flags.FLAG_REMOVE_IDLE_LOCATION);
+ pw.print("=");
+ pw.println(Flags.removeIdleLocation());
+ pw.println();
+
synchronized (this) {
mConstants.dump(pw);
@@ -5449,7 +5468,8 @@ public class DeviceIdleController extends SystemService
pw.println(" Temp whitelist schedule:");
prefix = " ";
}
- final long timeNow = SystemClock.elapsedRealtime();
+ final long timeNow = Flags.useCpuTimeForTempAllowlist() ? mInjector.getUptimeMillis()
+ : mInjector.getElapsedRealtime();
for (int i = 0; i < size; i++) {
pw.print(prefix);
pw.print("UID=");
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 033da2df9bf6..60ba3b896a28 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -282,7 +282,6 @@ public class AlarmManagerService extends SystemService {
private final Injector mInjector;
int mBroadcastRefCount = 0;
- boolean mUseFrozenStateToDropListenerAlarms;
MetricsHelper mMetricsHelper;
PowerManager.WakeLock mWakeLock;
SparseIntArray mAlarmsPerUid = new SparseIntArray();
@@ -1784,40 +1783,37 @@ public class AlarmManagerService extends SystemService {
mMetricsHelper = new MetricsHelper(getContext(), mLock);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
- mUseFrozenStateToDropListenerAlarms = Flags.useFrozenStateToDropListenerAlarms();
mStartUserBeforeScheduledAlarms = Flags.startUserBeforeScheduledAlarms()
&& UserManager.supportsMultipleUsers();
if (mStartUserBeforeScheduledAlarms) {
mUserWakeupStore = new UserWakeupStore();
mUserWakeupStore.init();
}
- if (mUseFrozenStateToDropListenerAlarms) {
- final ActivityManager.UidFrozenStateChangedCallback callback = (uids, frozenStates) -> {
- final int size = frozenStates.length;
- if (uids.length != size) {
- Slog.wtf(TAG, "Got different length arrays in frozen state callback!"
- + " uids.length: " + uids.length + " frozenStates.length: " + size);
- // Cannot process received data in any meaningful way.
- return;
- }
- final IntArray affectedUids = new IntArray();
- for (int i = 0; i < size; i++) {
- if (frozenStates[i] != UID_FROZEN_STATE_FROZEN) {
- continue;
- }
- if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED,
- uids[i])) {
- continue;
- }
- affectedUids.add(uids[i]);
+ final ActivityManager.UidFrozenStateChangedCallback callback = (uids, frozenStates) -> {
+ final int size = frozenStates.length;
+ if (uids.length != size) {
+ Slog.wtf(TAG, "Got different length arrays in frozen state callback!"
+ + " uids.length: " + uids.length + " frozenStates.length: " + size);
+ // Cannot process received data in any meaningful way.
+ return;
+ }
+ final IntArray affectedUids = new IntArray();
+ for (int i = 0; i < size; i++) {
+ if (frozenStates[i] != UID_FROZEN_STATE_FROZEN) {
+ continue;
}
- if (affectedUids.size() > 0) {
- removeExactListenerAlarms(affectedUids.toArray());
+ if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED,
+ uids[i])) {
+ continue;
}
- };
- final ActivityManager am = getContext().getSystemService(ActivityManager.class);
- am.registerUidFrozenStateChangedCallback(new HandlerExecutor(mHandler), callback);
- }
+ affectedUids.add(uids[i]);
+ }
+ if (affectedUids.size() > 0) {
+ removeExactListenerAlarms(affectedUids.toArray());
+ }
+ };
+ final ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ am.registerUidFrozenStateChangedCallback(new HandlerExecutor(mHandler), callback);
mListenerDeathRecipient = new IBinder.DeathRecipient() {
@Override
@@ -2994,13 +2990,10 @@ public class AlarmManagerService extends SystemService {
pw.println("Feature Flags:");
pw.increaseIndent();
- pw.print(Flags.FLAG_USE_FROZEN_STATE_TO_DROP_LISTENER_ALARMS,
- mUseFrozenStateToDropListenerAlarms);
- pw.println();
pw.print(Flags.FLAG_START_USER_BEFORE_SCHEDULED_ALARMS,
Flags.startUserBeforeScheduledAlarms());
- pw.decreaseIndent();
pw.println();
+ pw.decreaseIndent();
pw.println();
pw.println("App Standby Parole: " + mAppStandbyParole);
@@ -5146,38 +5139,6 @@ public class AlarmManagerService extends SystemService {
removeForStoppedLocked(uid);
}
}
-
- @Override
- public void handleUidCachedChanged(int uid, boolean cached) {
- if (mUseFrozenStateToDropListenerAlarms) {
- // Use ActivityManager#UidFrozenStateChangedCallback instead.
- return;
- }
- if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uid)) {
- return;
- }
- // Apps can quickly get frozen after being cached, breaking the exactness guarantee on
- // listener alarms. So going forward, the contract of exact listener alarms explicitly
- // states that they will be removed as soon as the app goes out of lifecycle. We still
- // allow a short grace period for quick shuffling of proc-states that may happen
- // unexpectedly when switching between different lifecycles and is generally hard for
- // apps to avoid.
-
- final long delay;
- synchronized (mLock) {
- delay = mConstants.CACHED_LISTENER_REMOVAL_DELAY;
- }
- final Integer uidObj = uid;
-
- if (cached && !mHandler.hasEqualMessages(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED,
- uidObj)) {
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED, uidObj),
- delay);
- } else {
- mHandler.removeEqualMessages(REMOVE_EXACT_LISTENER_ALARMS_ON_CACHED, uidObj);
- }
- }
};
private final BroadcastStats getStatsLocked(PendingIntent pi) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 197de37f8ac4..a5a08fb9997c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -44,6 +44,7 @@ import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.app.job.JobSnapshot;
import android.app.job.JobWorkItem;
+import android.app.job.PendingJobReasonsInfo;
import android.app.job.UserVisibleJobSummary;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
@@ -2099,8 +2100,12 @@ public class JobSchedulerService extends com.android.server.SystemService
if (DEBUG) {
Slog.v(TAG, debugPrefix + " ready=" + jobReady);
}
- if (!jobReady) {
- return job.getPendingJobReasons();
+ final JobRestriction restriction = checkIfRestricted(job);
+ if (DEBUG) {
+ Slog.v(TAG, debugPrefix + " restriction=" + restriction);
+ }
+ if (!jobReady || restriction != null) {
+ return job.getPendingJobReasons(restriction);
}
final boolean userStarted = areUsersStartedLocked(job);
@@ -2120,18 +2125,6 @@ public class JobSchedulerService extends com.android.server.SystemService
return new int[] { JobScheduler.PENDING_JOB_REASON_APP };
}
- final JobRestriction restriction = checkIfRestricted(job);
- if (DEBUG) {
- Slog.v(TAG, debugPrefix + " restriction=" + restriction);
- }
- if (restriction != null) {
- // Currently this will return _DEVICE_STATE because of thermal reasons.
- // TODO (b/372031023): does it make sense to move this along with the
- // pendingJobReasons() call above and also get the pending reasons from
- // all of the restriction controllers?
- return new int[] { restriction.getPendingReason() };
- }
-
// The following can be a little more expensive, so we are doing it later,
// but still before checking with the package manager!
final boolean jobPending = mPendingJobQueue.contains(job);
@@ -2155,6 +2148,20 @@ public class JobSchedulerService extends com.android.server.SystemService
return new int[] { JobScheduler.PENDING_JOB_REASON_UNDEFINED };
}
+ @NonNull
+ private List<PendingJobReasonsInfo> getPendingJobReasonsHistory(
+ int uid, String namespace, int jobId) {
+ synchronized (mLock) {
+ final JobStatus job = mJobs.getJobByUidAndJobId(uid, namespace, jobId);
+ if (job == null) {
+ // Job doesn't exist.
+ throw new IllegalArgumentException("Invalid job id");
+ }
+
+ return job.getPendingJobReasonsHistory();
+ }
+ }
+
private JobInfo getPendingJob(int uid, @Nullable String namespace, int jobId) {
synchronized (mLock) {
ArraySet<JobStatus> jobs = mJobs.getJobsByUid(uid);
@@ -5171,6 +5178,19 @@ public class JobSchedulerService extends com.android.server.SystemService
}
@Override
+ public List<PendingJobReasonsInfo> getPendingJobReasonsHistory(String namespace, int jobId)
+ throws RemoteException {
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return JobSchedulerService.this.getPendingJobReasonsHistory(
+ uid, validateNamespace(namespace), jobId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public void cancelAll() throws RemoteException {
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
@@ -5906,6 +5926,9 @@ public class JobSchedulerService extends com.android.server.SystemService
pw.print(android.app.job.Flags.FLAG_GET_PENDING_JOB_REASONS_API,
android.app.job.Flags.getPendingJobReasonsApi());
pw.println();
+ pw.print(android.app.job.Flags.FLAG_GET_PENDING_JOB_REASONS_HISTORY_API,
+ android.app.job.Flags.getPendingJobReasonsHistoryApi());
+ pw.println();
pw.decreaseIndent();
pw.println();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index a4a302450849..f3bc9c747f17 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -442,6 +442,9 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
case android.app.job.Flags.FLAG_GET_PENDING_JOB_REASONS_API:
pw.println(android.app.job.Flags.getPendingJobReasonsApi());
break;
+ case android.app.job.Flags.FLAG_GET_PENDING_JOB_REASONS_HISTORY_API:
+ pw.println(android.app.job.Flags.getPendingJobReasonsHistoryApi());
+ break;
default:
pw.println("Unknown flag: " + flagName);
break;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 0c5be2185c2b..5a33aa0ab7eb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -32,6 +32,7 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobWorkItem;
+import android.app.job.PendingJobReasonsInfo;
import android.app.job.UserVisibleJobSummary;
import android.content.ClipData;
import android.content.ComponentName;
@@ -39,6 +40,7 @@ import android.net.Network;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.text.format.DateFormat;
@@ -64,6 +66,7 @@ import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobServerProtoEnums;
import com.android.server.job.JobStatusDumpProto;
import com.android.server.job.JobStatusShortInfoProto;
+import com.android.server.job.restrictions.JobRestriction;
import dalvik.annotation.optimization.NeverCompile;
@@ -72,6 +75,7 @@ import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.function.Predicate;
@@ -521,6 +525,10 @@ public final class JobStatus {
private final long[] mConstraintUpdatedTimesElapsed = new long[NUM_CONSTRAINT_CHANGE_HISTORY];
private final int[] mConstraintStatusHistory = new int[NUM_CONSTRAINT_CHANGE_HISTORY];
+ private final List<PendingJobReasonsInfo> mPendingJobReasonsHistory = new ArrayList<>();
+ private static final int PENDING_JOB_HISTORY_RETURN_LIMIT = 10;
+ private static final int PENDING_JOB_HISTORY_TRIM_THRESHOLD = 25;
+
/**
* For use only by ContentObserverController: state it is maintaining about content URIs
* being observed.
@@ -2013,6 +2021,16 @@ public final class JobStatus {
mReasonReadyToUnready = JobParameters.STOP_REASON_UNDEFINED;
}
+ final int unsatisfiedConstraints = ~satisfiedConstraints
+ & (requiredConstraints | mDynamicConstraints | IMPLICIT_CONSTRAINTS);
+ populatePendingJobReasonsHistoryMap(isReady, nowElapsed, unsatisfiedConstraints);
+ final int historySize = mPendingJobReasonsHistory.size();
+ if (historySize >= PENDING_JOB_HISTORY_TRIM_THRESHOLD) {
+ // Ensure trimming doesn't occur too often - max history we currently return is 10
+ mPendingJobReasonsHistory.subList(0, historySize - PENDING_JOB_HISTORY_RETURN_LIMIT)
+ .clear();
+ }
+
return true;
}
@@ -2087,14 +2105,10 @@ public final class JobStatus {
}
}
- /**
- * This will return all potential reasons why the job is pending.
- */
@NonNull
- public int[] getPendingJobReasons() {
+ public ArrayList<Integer> constraintsToPendingJobReasons(int unsatisfiedConstraints) {
final ArrayList<Integer> reasons = new ArrayList<>();
- final int unsatisfiedConstraints = ~satisfiedConstraints
- & (requiredConstraints | mDynamicConstraints | IMPLICIT_CONSTRAINTS);
+
if ((CONSTRAINT_BACKGROUND_NOT_RESTRICTED & unsatisfiedConstraints) != 0) {
// The BACKGROUND_NOT_RESTRICTED constraint could be unsatisfied either because
// the app is background restricted, or because we're restricting background work
@@ -2180,6 +2194,27 @@ public final class JobStatus {
}
}
+ return reasons;
+ }
+
+ /**
+ * This will return all potential reasons why the job is pending.
+ */
+ @NonNull
+ public int[] getPendingJobReasons(@Nullable JobRestriction restriction) {
+ final int unsatisfiedConstraints = ~satisfiedConstraints
+ & (requiredConstraints | mDynamicConstraints | IMPLICIT_CONSTRAINTS);
+ final ArrayList<Integer> reasons = constraintsToPendingJobReasons(unsatisfiedConstraints);
+
+ if (restriction != null) {
+ // Currently only ThermalStatusRestriction extends the JobRestriction class and
+ // returns PENDING_JOB_REASON_DEVICE_STATE if the job is restricted because of thermal.
+ @JobScheduler.PendingJobReason final int reason = restriction.getPendingReason();
+ if (!reasons.contains(reason)) {
+ reasons.addLast(reason);
+ }
+ }
+
if (reasons.isEmpty()) {
if (getEffectiveStandbyBucket() == NEVER_INDEX) {
Slog.wtf(TAG, "App in NEVER bucket querying pending job reason");
@@ -2199,6 +2234,55 @@ public final class JobStatus {
return reasonsArr;
}
+ private void populatePendingJobReasonsHistoryMap(boolean isReady,
+ long constraintTimestamp, int unsatisfiedConstraints) {
+ final long constraintTimestampEpoch = // system_boot_time + constraint_satisfied_time
+ (System.currentTimeMillis() - SystemClock.elapsedRealtime()) + constraintTimestamp;
+
+ if (isReady) {
+ // Job is ready to execute. At this point, if the job doesn't execute, it might be
+ // because of the app itself; if not, note it as undefined (documented in javadoc).
+ mPendingJobReasonsHistory.addLast(
+ new PendingJobReasonsInfo(
+ constraintTimestampEpoch,
+ new int[] { serviceProcessName != null
+ ? JobScheduler.PENDING_JOB_REASON_APP
+ : JobScheduler.PENDING_JOB_REASON_UNDEFINED }));
+ return;
+ }
+
+ final ArrayList<Integer> reasons = constraintsToPendingJobReasons(unsatisfiedConstraints);
+ if (reasons.isEmpty()) {
+ // If the job is not waiting on any constraints to be met, note it as undefined.
+ reasons.add(JobScheduler.PENDING_JOB_REASON_UNDEFINED);
+ }
+
+ final int[] reasonsArr = new int[reasons.size()];
+ for (int i = 0; i < reasonsArr.length; i++) {
+ reasonsArr[i] = reasons.get(i);
+ }
+ mPendingJobReasonsHistory.addLast(
+ new PendingJobReasonsInfo(constraintTimestampEpoch, reasonsArr));
+ }
+
+ /**
+ * Returns the last {@link #PENDING_JOB_HISTORY_RETURN_LIMIT} constraint changes.
+ */
+ @NonNull
+ public List<PendingJobReasonsInfo> getPendingJobReasonsHistory() {
+ final List<PendingJobReasonsInfo> returnList =
+ new ArrayList<>(PENDING_JOB_HISTORY_RETURN_LIMIT);
+ final int historySize = mPendingJobReasonsHistory.size();
+ if (historySize != 0) {
+ returnList.addAll(
+ mPendingJobReasonsHistory.subList(
+ Math.max(0, historySize - PENDING_JOB_HISTORY_RETURN_LIMIT),
+ historySize));
+ }
+
+ return returnList;
+ }
+
/** @return whether or not the @param constraint is satisfied */
public boolean isConstraintSatisfied(int constraint) {
return (satisfiedConstraints&constraint) != 0;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 8bd3ef4f4d1a..637c726a9bd1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -36,10 +36,14 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.UidObserver;
+import android.app.compat.CompatChanges;
import android.app.job.JobInfo;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.UsageEventListener;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.Overridable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -132,6 +136,27 @@ public final class QuotaController extends StateController {
return (int) (val ^ (val >>> 32));
}
+ /**
+ * When enabled this change id overrides the default quota policy enforcement to the jobs
+ * running in the foreground process state.
+ */
+ // TODO: b/379681266 - Might need some refactoring for a better app-compat strategy.
+ @VisibleForTesting
+ @ChangeId
+ @Disabled // Disabled by default
+ @Overridable // The change can be overridden in user build
+ static final long OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS = 341201311L;
+
+ /**
+ * When enabled this change id overrides the default quota policy enforcement policy
+ * the jobs started when app was in the TOP state.
+ */
+ @VisibleForTesting
+ @ChangeId
+ @Disabled // Disabled by default
+ @Overridable // The change can be overridden in user build.
+ static final long OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS = 374323858L;
+
@VisibleForTesting
static class ExecutionStats {
/**
@@ -622,7 +647,9 @@ public final class QuotaController extends StateController {
}
final int uid = jobStatus.getSourceUid();
- if (!Flags.enforceQuotaPolicyToTopStartedJobs() && mTopAppCache.get(uid)) {
+ if ((!Flags.enforceQuotaPolicyToTopStartedJobs()
+ || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS,
+ uid)) && mTopAppCache.get(uid)) {
if (DEBUG) {
Slog.d(TAG, jobStatus.toShortString() + " is top started job");
}
@@ -659,7 +686,9 @@ public final class QuotaController extends StateController {
timer.stopTrackingJob(jobStatus);
}
}
- if (!Flags.enforceQuotaPolicyToTopStartedJobs()) {
+ if (!Flags.enforceQuotaPolicyToTopStartedJobs()
+ || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS,
+ jobStatus.getSourceUid())) {
mTopStartedJobs.remove(jobStatus);
}
}
@@ -772,7 +801,13 @@ public final class QuotaController extends StateController {
/** @return true if the job was started while the app was in the TOP state. */
private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) {
- return !Flags.enforceQuotaPolicyToTopStartedJobs() && mTopStartedJobs.contains(jobStatus);
+ if (!Flags.enforceQuotaPolicyToTopStartedJobs()
+ || CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS,
+ jobStatus.getSourceUid())) {
+ return mTopStartedJobs.contains(jobStatus);
+ }
+
+ return false;
}
/** Returns the maximum amount of time this job could run for. */
@@ -2634,9 +2669,13 @@ public final class QuotaController extends StateController {
}
@VisibleForTesting
- int getProcessStateQuotaFreeThreshold() {
- return Flags.enforceQuotaPolicyToFgsJobs() ? ActivityManager.PROCESS_STATE_BOUND_TOP :
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+ int getProcessStateQuotaFreeThreshold(int uid) {
+ if (Flags.enforceQuotaPolicyToFgsJobs()
+ && !CompatChanges.isChangeEnabled(OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS, uid)) {
+ return ActivityManager.PROCESS_STATE_BOUND_TOP;
+ }
+
+ return ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
private class QcHandler extends Handler {
@@ -2776,7 +2815,7 @@ public final class QuotaController extends StateController {
isQuotaFree = true;
} else {
final boolean reprocess;
- if (procState <= getProcessStateQuotaFreeThreshold()) {
+ if (procState <= getProcessStateQuotaFreeThreshold(uid)) {
reprocess = !mForegroundUids.get(uid);
mForegroundUids.put(uid, true);
isQuotaFree = true;
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index c9d340757c6b..9871d713178e 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -337,11 +337,11 @@ public class AppStandbyController
*/
long[] mAppStandbyElapsedThresholds = DEFAULT_ELAPSED_TIME_THRESHOLDS;
/** Minimum time a strong usage event should keep the bucket elevated. */
- long mStrongUsageTimeoutMillis = ConstantsObserver.DEFAULT_STRONG_USAGE_TIMEOUT;
+ long mStrongUsageTimeoutMillis = ConstantsObserver.DEFAULT_LEGACY_STRONG_USAGE_TIMEOUT;
/** Minimum time a notification seen event should keep the bucket elevated. */
long mNotificationSeenTimeoutMillis = ConstantsObserver.DEFAULT_NOTIFICATION_TIMEOUT;
/** Minimum time a slice pinned event should keep the bucket elevated. */
- long mSlicePinnedTimeoutMillis = ConstantsObserver.DEFAULT_SLICE_PINNED_TIMEOUT;
+ long mSlicePinnedTimeoutMillis = ConstantsObserver.DEFAULT_LEGACY_SLICE_PINNED_TIMEOUT;
/** The standby bucket that an app will be promoted on a notification-seen event */
int mNotificationSeenPromotedBucket =
ConstantsObserver.DEFAULT_NOTIFICATION_SEEN_PROMOTED_BUCKET;
@@ -362,7 +362,9 @@ public class AppStandbyController
/** Maximum time to wait for a prediction before using simple timeouts to downgrade buckets. */
long mPredictionTimeoutMillis = DEFAULT_PREDICTION_TIMEOUT;
/** Maximum time a sync adapter associated with a CP should keep the buckets elevated. */
- long mSyncAdapterTimeoutMillis = ConstantsObserver.DEFAULT_SYNC_ADAPTER_TIMEOUT;
+ long mSyncAdapterTimeoutMillis = ConstantsObserver.DEFAULT_LEGACY_SYNC_ADAPTER_TIMEOUT;
+ /** The bucket that an app will be promoted on a sync adapter associated with a CP */
+ int mSyncAdapaterPromotedBucket = STANDBY_BUCKET_ACTIVE;
/**
* Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
* non-doze
@@ -751,7 +753,7 @@ public class AppStandbyController
userId);
synchronized (mAppIdleLock) {
reportNoninteractiveUsageCrossUserLocked(packageName, userId,
- STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_SYNC_ADAPTER,
+ mSyncAdapaterPromotedBucket, REASON_SUB_USAGE_SYNC_ADAPTER,
elapsedRealtime, mSyncAdapterTimeoutMillis, linkedProfiles);
}
}
@@ -2446,6 +2448,8 @@ public class AppStandbyController
pw.println("Flags: ");
pw.println(" " + Flags.FLAG_AVOID_IDLE_CHECK
+ ": " + Flags.avoidIdleCheck());
+ pw.println(" " + Flags.FLAG_ADJUST_DEFAULT_BUCKET_ELEVATION_PARAMS
+ + ": " + Flags.adjustDefaultBucketElevationParams());
pw.println();
synchronized (mCarrierPrivilegedLock) {
@@ -2481,6 +2485,9 @@ public class AppStandbyController
pw.print(" mSyncAdapterTimeoutMillis=");
TimeUtils.formatDuration(mSyncAdapterTimeoutMillis, pw);
pw.println();
+ pw.print(" mSyncAdapaterPromotedBucket=");
+ pw.print(standbyBucketToString(mSyncAdapaterPromotedBucket));
+ pw.println();
pw.print(" mSystemInteractionTimeoutMillis=");
TimeUtils.formatDuration(mSystemInteractionTimeoutMillis, pw);
pw.println();
@@ -3059,12 +3066,18 @@ public class AppStandbyController
public static final long DEFAULT_CHECK_IDLE_INTERVAL_MS =
COMPRESS_TIME ? ONE_MINUTE : 4 * ONE_HOUR;
- public static final long DEFAULT_STRONG_USAGE_TIMEOUT =
+ public static final long DEFAULT_LEGACY_STRONG_USAGE_TIMEOUT =
COMPRESS_TIME ? ONE_MINUTE : 1 * ONE_HOUR;
+
+ public static final long DEFAULT_CURRENT_STRONG_USAGE_TIMEOUT =
+ COMPRESS_TIME ? ONE_MINUTE : 5 * ONE_MINUTE;
public static final long DEFAULT_NOTIFICATION_TIMEOUT =
COMPRESS_TIME ? 12 * ONE_MINUTE : 12 * ONE_HOUR;
- public static final long DEFAULT_SLICE_PINNED_TIMEOUT =
+ public static final long DEFAULT_LEGACY_SLICE_PINNED_TIMEOUT =
COMPRESS_TIME ? 12 * ONE_MINUTE : 12 * ONE_HOUR;
+
+ public static final long DEFAULT_CURRENT_SLICE_PINNED_TIMEOUT =
+ COMPRESS_TIME ? 12 * ONE_MINUTE : 2 * ONE_HOUR;
public static final int DEFAULT_NOTIFICATION_SEEN_PROMOTED_BUCKET =
STANDBY_BUCKET_WORKING_SET;
public static final boolean DEFAULT_RETAIN_NOTIFICATION_SEEN_IMPACT_FOR_PRE_T_APPS = false;
@@ -3073,8 +3086,11 @@ public class AppStandbyController
COMPRESS_TIME ? 2 * ONE_MINUTE : 2 * ONE_HOUR;
public static final long DEFAULT_SYSTEM_INTERACTION_TIMEOUT =
COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE;
- public static final long DEFAULT_SYNC_ADAPTER_TIMEOUT =
+ public static final long DEFAULT_LEGACY_SYNC_ADAPTER_TIMEOUT =
COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE;
+
+ public static final long DEFAULT_CURRENT_SYNC_ADAPTER_TIMEOUT =
+ COMPRESS_TIME ? ONE_MINUTE : 2 * ONE_HOUR;
public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT =
COMPRESS_TIME ? (ONE_MINUTE / 2) : 10 * ONE_MINUTE;
public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT =
@@ -3117,6 +3133,9 @@ public class AppStandbyController
cr.registerContentObserver(Global.getUriFor(Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED),
false, this);
mInjector.registerDeviceConfigPropertiesChangedListener(this);
+
+ processDefaultConstants();
+
// Load all the constants.
// postOneTimeCheckIdleStates() doesn't need to be called on boot.
processProperties(mInjector.getDeviceConfigProperties());
@@ -3135,6 +3154,17 @@ public class AppStandbyController
postOneTimeCheckIdleStates();
}
+ private void processDefaultConstants() {
+ if (!Flags.adjustDefaultBucketElevationParams()) {
+ return;
+ }
+
+ mSlicePinnedTimeoutMillis = DEFAULT_CURRENT_SLICE_PINNED_TIMEOUT;
+ mSyncAdapterTimeoutMillis = DEFAULT_CURRENT_SYNC_ADAPTER_TIMEOUT;
+ mSyncAdapaterPromotedBucket = STANDBY_BUCKET_WORKING_SET;
+ mStrongUsageTimeoutMillis = DEFAULT_CURRENT_STRONG_USAGE_TIMEOUT;
+ }
+
private void processProperties(DeviceConfig.Properties properties) {
boolean timeThresholdsUpdated = false;
synchronized (mAppIdleLock) {
@@ -3182,11 +3212,16 @@ public class AppStandbyController
case KEY_SLICE_PINNED_HOLD_DURATION:
mSlicePinnedTimeoutMillis = properties.getLong(
KEY_SLICE_PINNED_HOLD_DURATION,
- DEFAULT_SLICE_PINNED_TIMEOUT);
+ Flags.adjustDefaultBucketElevationParams()
+ ? DEFAULT_CURRENT_SLICE_PINNED_TIMEOUT
+ : DEFAULT_LEGACY_SLICE_PINNED_TIMEOUT);
break;
case KEY_STRONG_USAGE_HOLD_DURATION:
mStrongUsageTimeoutMillis = properties.getLong(
- KEY_STRONG_USAGE_HOLD_DURATION, DEFAULT_STRONG_USAGE_TIMEOUT);
+ KEY_STRONG_USAGE_HOLD_DURATION,
+ Flags.adjustDefaultBucketElevationParams()
+ ? DEFAULT_CURRENT_STRONG_USAGE_TIMEOUT
+ : DEFAULT_LEGACY_STRONG_USAGE_TIMEOUT);
break;
case KEY_PREDICTION_TIMEOUT:
mPredictionTimeoutMillis = properties.getLong(
@@ -3203,7 +3238,10 @@ public class AppStandbyController
break;
case KEY_SYNC_ADAPTER_HOLD_DURATION:
mSyncAdapterTimeoutMillis = properties.getLong(
- KEY_SYNC_ADAPTER_HOLD_DURATION, DEFAULT_SYNC_ADAPTER_TIMEOUT);
+ KEY_SYNC_ADAPTER_HOLD_DURATION,
+ Flags.adjustDefaultBucketElevationParams()
+ ? DEFAULT_CURRENT_SYNC_ADAPTER_TIMEOUT
+ : DEFAULT_LEGACY_SYNC_ADAPTER_TIMEOUT);
break;
case KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION:
mExemptedSyncScheduledDozeTimeoutMillis = properties.getLong(