Merge "Fix JobThrottling tests, take 2." into rvc-dev

This commit is contained in:
Kweku Adams
2020-02-27 15:44:46 +00:00
committed by Android (Google) Code Review
5 changed files with 68 additions and 18 deletions

View File

@@ -3033,6 +3033,10 @@ public class JobSchedulerService extends com.android.server.SystemService
return 0; return 0;
} }
void resetExecutionQuota(@NonNull String pkgName, int userId) {
mQuotaController.clearAppStats(pkgName, userId);
}
void resetScheduleQuota() { void resetScheduleQuota() {
mQuotaTracker.clear(); mQuotaTracker.clear();
} }

View File

@@ -66,6 +66,8 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
return getJobState(pw); return getJobState(pw);
case "heartbeat": case "heartbeat":
return doHeartbeat(pw); return doHeartbeat(pw);
case "reset-execution-quota":
return resetExecutionQuota(pw);
case "reset-schedule-quota": case "reset-schedule-quota":
return resetScheduleQuota(pw); return resetScheduleQuota(pw);
case "trigger-dock-state": case "trigger-dock-state":
@@ -346,6 +348,40 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
return -1; 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 { private int resetScheduleQuota(PrintWriter pw) throws Exception {
checkPermission("reset schedule quota"); checkPermission("reset schedule quota");

View File

@@ -16,6 +16,8 @@
package com.android.server.job.controllers; package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Log; import android.util.Log;
@@ -196,6 +198,9 @@ public final class BackgroundJobsController extends StateController {
} else { } else {
isActive = (activeState == KNOWN_ACTIVE); 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); boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
didChange |= jobStatus.setUidActive(isActive); didChange |= jobStatus.setUidActive(isActive);
return didChange; return didChange;

View File

@@ -1271,7 +1271,8 @@ public final class JobStatus {
// sessions (exempt from dynamic restrictions), we need the additional check to ensure // sessions (exempt from dynamic restrictions), we need the additional check to ensure
// that NEVER jobs don't run. // that NEVER jobs don't run.
// TODO: cleanup quota and standby bucket management so we don't need the additional checks // 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; return false;
} }
// Deadline constraint trumps other constraints besides quota and dynamic (except for // Deadline constraint trumps other constraints besides quota and dynamic (except for

View File

@@ -579,23 +579,7 @@ public final class QuotaController extends StateController {
Slog.wtf(TAG, "Told app removed but given null package name."); Slog.wtf(TAG, "Told app removed but given null package name.");
return; return;
} }
final int userId = UserHandle.getUserId(uid); clearAppStats(packageName, 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);
mForegroundUids.delete(uid); mForegroundUids.delete(uid);
mUidToPackageCache.remove(uid); mUidToPackageCache.remove(uid);
} }
@@ -610,6 +594,26 @@ public final class QuotaController extends StateController {
mUidToPackageCache.clear(); 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) { private boolean isUidInForeground(int uid) {
if (UserHandle.isCore(uid)) { if (UserHandle.isCore(uid)) {
return true; return true;