Fix JobThrottling tests, take 2.
1. Reset execution quotas between tests so earlier run tests don't affect later ones. 2. Ensure uidActive overrides even the NEVER bucket. Also log a wtf if we ever get into this situation. Bug: 138253466 Bug: 149931359 Test: atest android.jobscheduler.cts.JobThrottlingTest Change-Id: I1caf92fe8dda3c661ef68ca56c32fcd709e26856
This commit is contained in:
@@ -3015,6 +3015,10 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resetExecutionQuota(@NonNull String pkgName, int userId) {
|
||||
mQuotaController.clearAppStats(pkgName, userId);
|
||||
}
|
||||
|
||||
void resetScheduleQuota() {
|
||||
mQuotaTracker.clear();
|
||||
}
|
||||
|
||||
@@ -66,6 +66,8 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
|
||||
return getJobState(pw);
|
||||
case "heartbeat":
|
||||
return doHeartbeat(pw);
|
||||
case "reset-execution-quota":
|
||||
return resetExecutionQuota(pw);
|
||||
case "reset-schedule-quota":
|
||||
return resetScheduleQuota(pw);
|
||||
case "trigger-dock-state":
|
||||
@@ -346,6 +348,40 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int resetExecutionQuota(PrintWriter pw) throws Exception {
|
||||
checkPermission("reset execution quota");
|
||||
|
||||
int userId = UserHandle.USER_SYSTEM;
|
||||
|
||||
String opt;
|
||||
while ((opt = getNextOption()) != null) {
|
||||
switch (opt) {
|
||||
case "-u":
|
||||
case "--user":
|
||||
userId = UserHandle.parseUserArg(getNextArgRequired());
|
||||
break;
|
||||
|
||||
default:
|
||||
pw.println("Error: unknown option '" + opt + "'");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (userId == UserHandle.USER_CURRENT) {
|
||||
userId = ActivityManager.getCurrentUser();
|
||||
}
|
||||
|
||||
final String pkgName = getNextArgRequired();
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mInternal.resetExecutionQuota(pkgName, userId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int resetScheduleQuota(PrintWriter pw) throws Exception {
|
||||
checkPermission("reset schedule quota");
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.job.controllers;
|
||||
|
||||
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
@@ -196,6 +198,9 @@ public final class BackgroundJobsController extends StateController {
|
||||
} else {
|
||||
isActive = (activeState == KNOWN_ACTIVE);
|
||||
}
|
||||
if (isActive && jobStatus.getStandbyBucket() == NEVER_INDEX) {
|
||||
Slog.wtf(TAG, "App became active but still in NEVER bucket");
|
||||
}
|
||||
boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
|
||||
didChange |= jobStatus.setUidActive(isActive);
|
||||
return didChange;
|
||||
|
||||
@@ -1271,7 +1271,8 @@ public final class JobStatus {
|
||||
// sessions (exempt from dynamic restrictions), we need the additional check to ensure
|
||||
// that NEVER jobs don't run.
|
||||
// TODO: cleanup quota and standby bucket management so we don't need the additional checks
|
||||
if ((!mReadyWithinQuota && !mReadyDynamicSatisfied) || standbyBucket == NEVER_INDEX) {
|
||||
if ((!mReadyWithinQuota && !mReadyDynamicSatisfied)
|
||||
|| getEffectiveStandbyBucket() == NEVER_INDEX) {
|
||||
return false;
|
||||
}
|
||||
// Deadline constraint trumps other constraints besides quota and dynamic (except for
|
||||
|
||||
@@ -579,23 +579,7 @@ public final class QuotaController extends StateController {
|
||||
Slog.wtf(TAG, "Told app removed but given null package name.");
|
||||
return;
|
||||
}
|
||||
final int userId = UserHandle.getUserId(uid);
|
||||
mTrackedJobs.delete(userId, packageName);
|
||||
Timer timer = mPkgTimers.get(userId, packageName);
|
||||
if (timer != null) {
|
||||
if (timer.isActive()) {
|
||||
Slog.wtf(TAG, "onAppRemovedLocked called before Timer turned off.");
|
||||
timer.dropEverythingLocked();
|
||||
}
|
||||
mPkgTimers.delete(userId, packageName);
|
||||
}
|
||||
mTimingSessions.delete(userId, packageName);
|
||||
QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
|
||||
if (alarmListener != null) {
|
||||
mAlarmManager.cancel(alarmListener);
|
||||
mInQuotaAlarmListeners.delete(userId, packageName);
|
||||
}
|
||||
mExecutionStatsCache.delete(userId, packageName);
|
||||
clearAppStats(packageName, UserHandle.getUserId(uid));
|
||||
mForegroundUids.delete(uid);
|
||||
mUidToPackageCache.remove(uid);
|
||||
}
|
||||
@@ -610,6 +594,26 @@ public final class QuotaController extends StateController {
|
||||
mUidToPackageCache.clear();
|
||||
}
|
||||
|
||||
/** Drop all historical stats and stop tracking any active sessions for the specified app. */
|
||||
public void clearAppStats(@NonNull String packageName, int userId) {
|
||||
mTrackedJobs.delete(userId, packageName);
|
||||
Timer timer = mPkgTimers.get(userId, packageName);
|
||||
if (timer != null) {
|
||||
if (timer.isActive()) {
|
||||
Slog.e(TAG, "clearAppStats called before Timer turned off.");
|
||||
timer.dropEverythingLocked();
|
||||
}
|
||||
mPkgTimers.delete(userId, packageName);
|
||||
}
|
||||
mTimingSessions.delete(userId, packageName);
|
||||
QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
|
||||
if (alarmListener != null) {
|
||||
mAlarmManager.cancel(alarmListener);
|
||||
mInQuotaAlarmListeners.delete(userId, packageName);
|
||||
}
|
||||
mExecutionStatsCache.delete(userId, packageName);
|
||||
}
|
||||
|
||||
private boolean isUidInForeground(int uid) {
|
||||
if (UserHandle.isCore(uid)) {
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user