Merge "Move JobServiceContext handling to the concurrency manager." into tm-dev
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.job;
|
package com.android.server.job;
|
||||||
|
|
||||||
import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
|
import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
|
||||||
|
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
|
||||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
@@ -32,9 +33,11 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
|
import android.os.BatteryStats;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
@@ -51,19 +54,24 @@ import android.util.proto.ProtoOutputStream;
|
|||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.app.IBatteryStats;
|
||||||
import com.android.internal.app.procstats.ProcessStats;
|
import com.android.internal.app.procstats.ProcessStats;
|
||||||
import com.android.internal.util.StatLogger;
|
import com.android.internal.util.StatLogger;
|
||||||
import com.android.server.JobSchedulerBackgroundThread;
|
import com.android.server.JobSchedulerBackgroundThread;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.job.controllers.JobStatus;
|
import com.android.server.job.controllers.JobStatus;
|
||||||
import com.android.server.job.controllers.StateController;
|
import com.android.server.job.controllers.StateController;
|
||||||
|
import com.android.server.job.restrictions.JobRestriction;
|
||||||
import com.android.server.pm.UserManagerInternal;
|
import com.android.server.pm.UserManagerInternal;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class decides, given the various configuration and the system status, which jobs can start
|
* This class decides, given the various configuration and the system status, which jobs can start
|
||||||
@@ -278,6 +286,11 @@ class JobConcurrencyManager {
|
|||||||
|
|
||||||
String[] mRecycledShouldStopJobReason = new String[MAX_JOB_CONTEXTS_COUNT];
|
String[] mRecycledShouldStopJobReason = new String[MAX_JOB_CONTEXTS_COUNT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of JobServiceContexts that we use to run jobs.
|
||||||
|
*/
|
||||||
|
final List<JobServiceContext> mActiveServices = new ArrayList<>();
|
||||||
|
|
||||||
private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>();
|
private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>();
|
||||||
|
|
||||||
private final WorkCountTracker mWorkCountTracker = new WorkCountTracker();
|
private final WorkCountTracker mWorkCountTracker = new WorkCountTracker();
|
||||||
@@ -358,6 +371,20 @@ class JobConcurrencyManager {
|
|||||||
onInteractiveStateChanged(mPowerManager.isInteractive());
|
onInteractiveStateChanged(mPowerManager.isInteractive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the boot phase reaches
|
||||||
|
* {@link com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START}.
|
||||||
|
*/
|
||||||
|
void onThirdPartyAppsCanStart() {
|
||||||
|
final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface(
|
||||||
|
ServiceManager.getService(BatteryStats.SERVICE_NAME));
|
||||||
|
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
|
||||||
|
mActiveServices.add(
|
||||||
|
new JobServiceContext(mService, this, batteryStats,
|
||||||
|
mService.mJobPackageTracker, mContext.getMainLooper()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
void onAppRemovedLocked(String pkgName, int uid) {
|
void onAppRemovedLocked(String pkgName, int uid) {
|
||||||
final PackageStats packageStats = mActivePkgStats.get(UserHandle.getUserId(uid), pkgName);
|
final PackageStats packageStats = mActivePkgStats.get(UserHandle.getUserId(uid), pkgName);
|
||||||
@@ -390,6 +417,7 @@ class JobConcurrencyManager {
|
|||||||
case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
|
case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
|
||||||
if (mPowerManager != null && mPowerManager.isDeviceIdleMode()) {
|
if (mPowerManager != null && mPowerManager.isDeviceIdleMode()) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
stopUnexemptedJobsForDoze();
|
||||||
stopLongRunningJobsLocked("deep doze");
|
stopLongRunningJobsLocked("deep doze");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,6 +498,11 @@ class JobConcurrencyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
ArraySet<JobStatus> getRunningJobsLocked() {
|
||||||
|
return mRunningJobs;
|
||||||
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
boolean isJobRunningLocked(JobStatus job) {
|
boolean isJobRunningLocked(JobStatus job) {
|
||||||
return mRunningJobs.contains(job);
|
return mRunningJobs.contains(job);
|
||||||
@@ -546,7 +579,7 @@ class JobConcurrencyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<JobStatus> pendingJobs = mService.mPendingJobs;
|
final List<JobStatus> pendingJobs = mService.mPendingJobs;
|
||||||
final List<JobServiceContext> activeServices = mService.mActiveServices;
|
final List<JobServiceContext> activeServices = mActiveServices;
|
||||||
|
|
||||||
// To avoid GC churn, we recycle the arrays.
|
// To avoid GC churn, we recycle the arrays.
|
||||||
JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap;
|
JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap;
|
||||||
@@ -718,10 +751,45 @@ class JobConcurrencyManager {
|
|||||||
noteConcurrency();
|
noteConcurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
boolean stopJobOnServiceContextLocked(JobStatus job,
|
||||||
|
@JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
|
||||||
|
if (!mRunningJobs.contains(job)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < mActiveServices.size(); i++) {
|
||||||
|
JobServiceContext jsc = mActiveServices.get(i);
|
||||||
|
final JobStatus executing = jsc.getRunningJobLocked();
|
||||||
|
if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
|
||||||
|
jsc.cancelExecutingJobLocked(reason, internalReasonCode, debugReason);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Slog.wtf(TAG, "Couldn't find running job on a context");
|
||||||
|
mRunningJobs.remove(job);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private void stopUnexemptedJobsForDoze() {
|
||||||
|
// When becoming idle, make sure no jobs are actively running,
|
||||||
|
// except those using the idle exemption flag.
|
||||||
|
for (int i = 0; i < mActiveServices.size(); i++) {
|
||||||
|
JobServiceContext jsc = mActiveServices.get(i);
|
||||||
|
final JobStatus executing = jsc.getRunningJobLocked();
|
||||||
|
if (executing != null && !executing.canRunInDoze()) {
|
||||||
|
jsc.cancelExecutingJobLocked(JobParameters.STOP_REASON_DEVICE_STATE,
|
||||||
|
JobParameters.INTERNAL_STOP_REASON_DEVICE_IDLE,
|
||||||
|
"cancelled due to doze");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private void stopLongRunningJobsLocked(@NonNull String debugReason) {
|
private void stopLongRunningJobsLocked(@NonNull String debugReason) {
|
||||||
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; ++i) {
|
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; ++i) {
|
||||||
final JobServiceContext jsc = mService.mActiveServices.get(i);
|
final JobServiceContext jsc = mActiveServices.get(i);
|
||||||
final JobStatus jobStatus = jsc.getRunningJobLocked();
|
final JobStatus jobStatus = jsc.getRunningJobLocked();
|
||||||
|
|
||||||
if (jobStatus != null && !jsc.isWithinExecutionGuaranteeTime()) {
|
if (jobStatus != null && !jsc.isWithinExecutionGuaranteeTime()) {
|
||||||
@@ -731,6 +799,41 @@ class JobConcurrencyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
void stopNonReadyActiveJobsLocked() {
|
||||||
|
for (int i = 0; i < mActiveServices.size(); i++) {
|
||||||
|
JobServiceContext serviceContext = mActiveServices.get(i);
|
||||||
|
final JobStatus running = serviceContext.getRunningJobLocked();
|
||||||
|
if (running == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!running.isReady()) {
|
||||||
|
if (running.getEffectiveStandbyBucket() == RESTRICTED_INDEX
|
||||||
|
&& running.getStopReason() == JobParameters.STOP_REASON_APP_STANDBY) {
|
||||||
|
serviceContext.cancelExecutingJobLocked(
|
||||||
|
running.getStopReason(),
|
||||||
|
JobParameters.INTERNAL_STOP_REASON_RESTRICTED_BUCKET,
|
||||||
|
"cancelled due to restricted bucket");
|
||||||
|
} else {
|
||||||
|
serviceContext.cancelExecutingJobLocked(
|
||||||
|
running.getStopReason(),
|
||||||
|
JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED,
|
||||||
|
"cancelled due to unsatisfied constraints");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final JobRestriction restriction = mService.checkIfRestricted(running);
|
||||||
|
if (restriction != null) {
|
||||||
|
final int internalReasonCode = restriction.getInternalReason();
|
||||||
|
serviceContext.cancelExecutingJobLocked(restriction.getReason(),
|
||||||
|
internalReasonCode,
|
||||||
|
"restricted due to "
|
||||||
|
+ JobParameters.getInternalReasonCodeDescription(
|
||||||
|
internalReasonCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void noteConcurrency() {
|
private void noteConcurrency() {
|
||||||
mService.mJobPackageTracker.noteConcurrency(mRunningJobs.size(),
|
mService.mJobPackageTracker.noteConcurrency(mRunningJobs.size(),
|
||||||
// TODO: log per type instead of only TOP
|
// TODO: log per type instead of only TOP
|
||||||
@@ -1077,6 +1180,24 @@ class JobConcurrencyManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
boolean executeTimeoutCommandLocked(PrintWriter pw, String pkgName, int userId,
|
||||||
|
boolean hasJobId, int jobId) {
|
||||||
|
boolean foundSome = false;
|
||||||
|
for (int i = 0; i < mActiveServices.size(); i++) {
|
||||||
|
final JobServiceContext jc = mActiveServices.get(i);
|
||||||
|
final JobStatus js = jc.getRunningJobLocked();
|
||||||
|
if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) {
|
||||||
|
foundSome = true;
|
||||||
|
pw.print("Timing out: ");
|
||||||
|
js.printUniqueId(pw);
|
||||||
|
pw.print(" ");
|
||||||
|
pw.println(js.getServiceComponent().flattenToShortString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return foundSome;
|
||||||
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private String printPendingQueueLocked() {
|
private String printPendingQueueLocked() {
|
||||||
StringBuilder s = new StringBuilder("Pending queue: ");
|
StringBuilder s = new StringBuilder("Pending queue: ");
|
||||||
@@ -1200,6 +1321,43 @@ class JobConcurrencyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
void dumpActiveJobsLocked(IndentingPrintWriter pw, Predicate<JobStatus> predicate,
|
||||||
|
long nowElapsed, long nowUptime) {
|
||||||
|
pw.println("Active jobs:");
|
||||||
|
pw.increaseIndent();
|
||||||
|
for (int i = 0; i < mActiveServices.size(); i++) {
|
||||||
|
JobServiceContext jsc = mActiveServices.get(i);
|
||||||
|
final JobStatus job = jsc.getRunningJobLocked();
|
||||||
|
|
||||||
|
if (job != null && !predicate.test(job)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pw.print("Slot #"); pw.print(i); pw.print(": ");
|
||||||
|
jsc.dumpLocked(pw, nowElapsed);
|
||||||
|
|
||||||
|
if (job != null) {
|
||||||
|
pw.increaseIndent();
|
||||||
|
|
||||||
|
pw.increaseIndent();
|
||||||
|
job.dump(pw, false, nowElapsed);
|
||||||
|
pw.decreaseIndent();
|
||||||
|
|
||||||
|
pw.print("Evaluated bias: ");
|
||||||
|
pw.println(JobInfo.getBiasString(job.lastEvaluatedBias));
|
||||||
|
|
||||||
|
pw.print("Active at ");
|
||||||
|
TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
|
||||||
|
pw.print(", pending for ");
|
||||||
|
TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
|
||||||
|
pw.decreaseIndent();
|
||||||
|
pw.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
|
|
||||||
public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) {
|
public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) {
|
||||||
final long token = proto.start(tag);
|
final long token = proto.start(tag);
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import android.content.pm.ServiceInfo;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.os.BatteryManagerInternal;
|
import android.os.BatteryManagerInternal;
|
||||||
import android.os.BatteryStats;
|
|
||||||
import android.os.BatteryStatsInternal;
|
import android.os.BatteryStatsInternal;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -67,7 +66,6 @@ import android.os.Message;
|
|||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
@@ -90,7 +88,6 @@ import android.util.proto.ProtoOutputStream;
|
|||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.app.IBatteryStats;
|
|
||||||
import com.android.internal.os.SomeArgs;
|
import com.android.internal.os.SomeArgs;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.DumpUtils;
|
import com.android.internal.util.DumpUtils;
|
||||||
@@ -100,7 +97,6 @@ import com.android.server.AppStateTrackerImpl;
|
|||||||
import com.android.server.DeviceIdleInternal;
|
import com.android.server.DeviceIdleInternal;
|
||||||
import com.android.server.JobSchedulerBackgroundThread;
|
import com.android.server.JobSchedulerBackgroundThread;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
|
|
||||||
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
|
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
|
||||||
import com.android.server.job.controllers.BackgroundJobsController;
|
import com.android.server.job.controllers.BackgroundJobsController;
|
||||||
import com.android.server.job.controllers.BatteryController;
|
import com.android.server.job.controllers.BatteryController;
|
||||||
@@ -243,12 +239,6 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
static final int MSG_CHECK_CHANGED_JOB_LIST = 8;
|
static final int MSG_CHECK_CHANGED_JOB_LIST = 8;
|
||||||
static final int MSG_CHECK_MEDIA_EXEMPTION = 9;
|
static final int MSG_CHECK_MEDIA_EXEMPTION = 9;
|
||||||
|
|
||||||
/**
|
|
||||||
* Track Services that have currently active or pending jobs. The index is provided by
|
|
||||||
* {@link JobStatus#getServiceToken()}
|
|
||||||
*/
|
|
||||||
final List<JobServiceContext> mActiveServices = new ArrayList<>();
|
|
||||||
|
|
||||||
/** List of controllers that will notify this service of updates to jobs. */
|
/** List of controllers that will notify this service of updates to jobs. */
|
||||||
final List<StateController> mControllers;
|
final List<StateController> mControllers;
|
||||||
/**
|
/**
|
||||||
@@ -307,7 +297,6 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
|
|
||||||
PackageManagerInternal mLocalPM;
|
PackageManagerInternal mLocalPM;
|
||||||
ActivityManagerInternal mActivityManagerInternal;
|
ActivityManagerInternal mActivityManagerInternal;
|
||||||
IBatteryStats mBatteryStats;
|
|
||||||
DeviceIdleInternal mLocalDeviceIdleController;
|
DeviceIdleInternal mLocalDeviceIdleController;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
AppStateTrackerImpl mAppStateTracker;
|
AppStateTrackerImpl mAppStateTracker;
|
||||||
@@ -1578,7 +1567,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
mJobPackageTracker.noteNonpending(cancelled);
|
mJobPackageTracker.noteNonpending(cancelled);
|
||||||
}
|
}
|
||||||
// Cancel if running.
|
// Cancel if running.
|
||||||
stopJobOnServiceContextLocked(cancelled, reason, internalReasonCode, debugReason);
|
mConcurrencyManager.stopJobOnServiceContextLocked(
|
||||||
|
cancelled, reason, internalReasonCode, debugReason);
|
||||||
// If this is a replacement, bring in the new version of the job
|
// If this is a replacement, bring in the new version of the job
|
||||||
if (incomingJob != null) {
|
if (incomingJob != null) {
|
||||||
if (DEBUG) Slog.i(TAG, "Tracking replacement job " + incomingJob.toShortString());
|
if (DEBUG) Slog.i(TAG, "Tracking replacement job " + incomingJob.toShortString());
|
||||||
@@ -1627,19 +1617,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Doze state changed: " + deviceIdle);
|
Slog.d(TAG, "Doze state changed: " + deviceIdle);
|
||||||
}
|
}
|
||||||
if (deviceIdle) {
|
if (!deviceIdle) {
|
||||||
// When becoming idle, make sure no jobs are actively running,
|
|
||||||
// except those using the idle exemption flag.
|
|
||||||
for (int i=0; i<mActiveServices.size(); i++) {
|
|
||||||
JobServiceContext jsc = mActiveServices.get(i);
|
|
||||||
final JobStatus executing = jsc.getRunningJobLocked();
|
|
||||||
if (executing != null && !executing.canRunInDoze()) {
|
|
||||||
jsc.cancelExecutingJobLocked(JobParameters.STOP_REASON_DEVICE_STATE,
|
|
||||||
JobParameters.INTERNAL_STOP_REASON_DEVICE_IDLE,
|
|
||||||
"cancelled due to doze");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// When coming out of idle, allow thing to start back up.
|
// When coming out of idle, allow thing to start back up.
|
||||||
if (mReadyToRock) {
|
if (mReadyToRock) {
|
||||||
if (mLocalDeviceIdleController != null) {
|
if (mLocalDeviceIdleController != null) {
|
||||||
@@ -1682,10 +1660,10 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
// active is true if pending queue contains jobs OR some job is running.
|
// active is true if pending queue contains jobs OR some job is running.
|
||||||
boolean active = mPendingJobs.size() > 0;
|
boolean active = mPendingJobs.size() > 0;
|
||||||
if (mPendingJobs.size() <= 0) {
|
if (mPendingJobs.size() <= 0) {
|
||||||
for (int i=0; i<mActiveServices.size(); i++) {
|
final ArraySet<JobStatus> runningJobs = mConcurrencyManager.getRunningJobsLocked();
|
||||||
final JobServiceContext jsc = mActiveServices.get(i);
|
for (int i = runningJobs.size() - 1; i >= 0; --i) {
|
||||||
final JobStatus job = jsc.getRunningJobLocked();
|
final JobStatus job = runningJobs.valueAt(i);
|
||||||
if (job != null && !job.canRunInDoze()) {
|
if (!job.canRunInDoze()) {
|
||||||
// We will report active if we have a job running and it does not have an
|
// We will report active if we have a job running and it does not have an
|
||||||
// exception that allows it to run in Doze.
|
// exception that allows it to run in Doze.
|
||||||
active = true;
|
active = true;
|
||||||
@@ -1895,16 +1873,9 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// Let's go!
|
// Let's go!
|
||||||
mReadyToRock = true;
|
mReadyToRock = true;
|
||||||
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
|
|
||||||
BatteryStats.SERVICE_NAME));
|
|
||||||
mLocalDeviceIdleController =
|
mLocalDeviceIdleController =
|
||||||
LocalServices.getService(DeviceIdleInternal.class);
|
LocalServices.getService(DeviceIdleInternal.class);
|
||||||
// Create the "runners".
|
mConcurrencyManager.onThirdPartyAppsCanStart();
|
||||||
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
|
|
||||||
mActiveServices.add(
|
|
||||||
new JobServiceContext(this, mConcurrencyManager, mBatteryStats,
|
|
||||||
mJobPackageTracker, getContext().getMainLooper()));
|
|
||||||
}
|
|
||||||
// Attach jobs to their controllers.
|
// Attach jobs to their controllers.
|
||||||
mJobs.forEachJob((job) -> {
|
mJobs.forEachJob((job) -> {
|
||||||
for (int controller = 0; controller < mControllers.size(); controller++) {
|
for (int controller = 0; controller < mControllers.size(); controller++) {
|
||||||
@@ -1961,19 +1932,6 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean stopJobOnServiceContextLocked(JobStatus job,
|
|
||||||
@JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
|
|
||||||
for (int i = 0; i < mActiveServices.size(); i++) {
|
|
||||||
JobServiceContext jsc = mActiveServices.get(i);
|
|
||||||
final JobStatus executing = jsc.getRunningJobLocked();
|
|
||||||
if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
|
|
||||||
jsc.cancelExecutingJobLocked(reason, internalReasonCode, debugReason);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return {@code true} if the specified job is currently executing. */
|
/** Return {@code true} if the specified job is currently executing. */
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
public boolean isCurrentlyRunningLocked(JobStatus job) {
|
public boolean isCurrentlyRunningLocked(JobStatus job) {
|
||||||
@@ -2383,7 +2341,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
* - if passes all the restrictions or has {@link JobInfo#BIAS_FOREGROUND_SERVICE} bias
|
* - if passes all the restrictions or has {@link JobInfo#BIAS_FOREGROUND_SERVICE} bias
|
||||||
* or higher.
|
* or higher.
|
||||||
*/
|
*/
|
||||||
private JobRestriction checkIfRestricted(JobStatus job) {
|
@GuardedBy("mLock")
|
||||||
|
JobRestriction checkIfRestricted(JobStatus job) {
|
||||||
if (evaluateJobBiasLocked(job) >= JobInfo.BIAS_FOREGROUND_SERVICE) {
|
if (evaluateJobBiasLocked(job) >= JobInfo.BIAS_FOREGROUND_SERVICE) {
|
||||||
// Jobs with BIAS_FOREGROUND_SERVICE or higher should not be restricted
|
// Jobs with BIAS_FOREGROUND_SERVICE or higher should not be restricted
|
||||||
return null;
|
return null;
|
||||||
@@ -2397,38 +2356,9 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
private void stopNonReadyActiveJobsLocked() {
|
private void stopNonReadyActiveJobsLocked() {
|
||||||
for (int i=0; i<mActiveServices.size(); i++) {
|
mConcurrencyManager.stopNonReadyActiveJobsLocked();
|
||||||
JobServiceContext serviceContext = mActiveServices.get(i);
|
|
||||||
final JobStatus running = serviceContext.getRunningJobLocked();
|
|
||||||
if (running == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!running.isReady()) {
|
|
||||||
if (running.getEffectiveStandbyBucket() == RESTRICTED_INDEX
|
|
||||||
&& running.getStopReason() == JobParameters.STOP_REASON_APP_STANDBY) {
|
|
||||||
serviceContext.cancelExecutingJobLocked(
|
|
||||||
running.getStopReason(),
|
|
||||||
JobParameters.INTERNAL_STOP_REASON_RESTRICTED_BUCKET,
|
|
||||||
"cancelled due to restricted bucket");
|
|
||||||
} else {
|
|
||||||
serviceContext.cancelExecutingJobLocked(
|
|
||||||
running.getStopReason(),
|
|
||||||
JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED,
|
|
||||||
"cancelled due to unsatisfied constraints");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final JobRestriction restriction = checkIfRestricted(running);
|
|
||||||
if (restriction != null) {
|
|
||||||
final int internalReasonCode = restriction.getInternalReason();
|
|
||||||
serviceContext.cancelExecutingJobLocked(restriction.getReason(),
|
|
||||||
internalReasonCode,
|
|
||||||
"restricted due to "
|
|
||||||
+ JobParameters.getInternalReasonCodeDescription(
|
|
||||||
internalReasonCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2598,7 +2528,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
debugReason = "couldn't figure out why the job should stop running";
|
debugReason = "couldn't figure out why the job should stop running";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stopJobOnServiceContextLocked(job, job.getStopReason(),
|
mConcurrencyManager.stopJobOnServiceContextLocked(job, job.getStopReason(),
|
||||||
internalStopReason, debugReason);
|
internalStopReason, debugReason);
|
||||||
} else if (mPendingJobs.remove(job)) {
|
} else if (mPendingJobs.remove(job)) {
|
||||||
noteJobNonPending(job);
|
noteJobNonPending(job);
|
||||||
@@ -3516,9 +3446,11 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
final ArrayList<JobInfo> runningJobs;
|
final ArrayList<JobInfo> runningJobs;
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
runningJobs = new ArrayList<>(mActiveServices.size());
|
final ArraySet<JobStatus> runningJobStatuses =
|
||||||
for (JobServiceContext jsc : mActiveServices) {
|
mConcurrencyManager.getRunningJobsLocked();
|
||||||
final JobStatus job = jsc.getRunningJobLocked();
|
runningJobs = new ArrayList<>(runningJobStatuses.size());
|
||||||
|
for (int i = runningJobStatuses.size() - 1; i >= 0; --i) {
|
||||||
|
final JobStatus job = runningJobStatuses.valueAt(i);
|
||||||
if (job != null) {
|
if (job != null) {
|
||||||
runningJobs.add(job.getJob());
|
runningJobs.add(job.getJob());
|
||||||
}
|
}
|
||||||
@@ -3599,18 +3531,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
boolean foundSome = false;
|
final boolean foundSome = mConcurrencyManager.executeTimeoutCommandLocked(pw,
|
||||||
for (int i = 0; i < mActiveServices.size(); i++) {
|
pkgName, userId, hasJobId, jobId);
|
||||||
final JobServiceContext jc = mActiveServices.get(i);
|
|
||||||
final JobStatus js = jc.getRunningJobLocked();
|
|
||||||
if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) {
|
|
||||||
foundSome = true;
|
|
||||||
pw.print("Timing out: ");
|
|
||||||
js.printUniqueId(pw);
|
|
||||||
pw.print(" ");
|
|
||||||
pw.println(js.getServiceComponent().flattenToShortString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!foundSome) {
|
if (!foundSome) {
|
||||||
pw.println("No matching executing jobs found.");
|
pw.println("No matching executing jobs found.");
|
||||||
}
|
}
|
||||||
@@ -4037,38 +3959,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.println("Active jobs:");
|
mConcurrencyManager.dumpActiveJobsLocked(pw, predicate, nowElapsed, nowUptime);
|
||||||
pw.increaseIndent();
|
|
||||||
for (int i=0; i<mActiveServices.size(); i++) {
|
|
||||||
JobServiceContext jsc = mActiveServices.get(i);
|
|
||||||
final JobStatus job = jsc.getRunningJobLocked();
|
|
||||||
|
|
||||||
if (job != null && !predicate.test(job)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pw.print("Slot #"); pw.print(i); pw.print(": ");
|
|
||||||
jsc.dumpLocked(pw, nowElapsed);
|
|
||||||
|
|
||||||
if (job != null) {
|
|
||||||
pw.increaseIndent();
|
|
||||||
|
|
||||||
pw.increaseIndent();
|
|
||||||
job.dump(pw, false, nowElapsed);
|
|
||||||
pw.decreaseIndent();
|
|
||||||
|
|
||||||
pw.print("Evaluated bias: ");
|
|
||||||
pw.println(JobInfo.getBiasString(job.lastEvaluatedBias));
|
|
||||||
|
|
||||||
pw.print("Active at ");
|
|
||||||
TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
|
|
||||||
pw.print(", pending for ");
|
|
||||||
TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
|
|
||||||
pw.decreaseIndent();
|
|
||||||
pw.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pw.decreaseIndent();
|
|
||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
boolean recentPrinted = false;
|
boolean recentPrinted = false;
|
||||||
@@ -4228,45 +4119,6 @@ public class JobSchedulerService extends com.android.server.SystemService
|
|||||||
|
|
||||||
proto.end(pjToken);
|
proto.end(pjToken);
|
||||||
}
|
}
|
||||||
for (JobServiceContext jsc : mActiveServices) {
|
|
||||||
final long ajToken = proto.start(JobSchedulerServiceDumpProto.ACTIVE_JOBS);
|
|
||||||
final JobStatus job = jsc.getRunningJobLocked();
|
|
||||||
|
|
||||||
if (job == null) {
|
|
||||||
final long ijToken = proto.start(ActiveJob.INACTIVE);
|
|
||||||
|
|
||||||
proto.write(ActiveJob.InactiveJob.TIME_SINCE_STOPPED_MS,
|
|
||||||
nowElapsed - jsc.mStoppedTime);
|
|
||||||
if (jsc.mStoppedReason != null) {
|
|
||||||
proto.write(ActiveJob.InactiveJob.STOPPED_REASON,
|
|
||||||
jsc.mStoppedReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
proto.end(ijToken);
|
|
||||||
} else {
|
|
||||||
final long rjToken = proto.start(ActiveJob.RUNNING);
|
|
||||||
|
|
||||||
job.writeToShortProto(proto, ActiveJob.RunningJob.INFO);
|
|
||||||
|
|
||||||
proto.write(ActiveJob.RunningJob.RUNNING_DURATION_MS,
|
|
||||||
nowElapsed - jsc.getExecutionStartTimeElapsed());
|
|
||||||
proto.write(ActiveJob.RunningJob.TIME_UNTIL_TIMEOUT_MS,
|
|
||||||
jsc.getTimeoutElapsed() - nowElapsed);
|
|
||||||
|
|
||||||
job.dump(proto, ActiveJob.RunningJob.DUMP, false, nowElapsed);
|
|
||||||
|
|
||||||
proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY,
|
|
||||||
evaluateJobBiasLocked(job));
|
|
||||||
|
|
||||||
proto.write(ActiveJob.RunningJob.TIME_SINCE_MADE_ACTIVE_MS,
|
|
||||||
nowUptime - job.madeActive);
|
|
||||||
proto.write(ActiveJob.RunningJob.PENDING_DURATION_MS,
|
|
||||||
job.madeActive - job.madePending);
|
|
||||||
|
|
||||||
proto.end(rjToken);
|
|
||||||
}
|
|
||||||
proto.end(ajToken);
|
|
||||||
}
|
|
||||||
if (filterUid == -1) {
|
if (filterUid == -1) {
|
||||||
proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock);
|
proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock);
|
||||||
proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive);
|
proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive);
|
||||||
|
|||||||
@@ -441,11 +441,6 @@ public final class JobStatus {
|
|||||||
/** The reason a job most recently went from ready to not ready. */
|
/** The reason a job most recently went from ready to not ready. */
|
||||||
private int mReasonReadyToUnready = JobParameters.STOP_REASON_UNDEFINED;
|
private int mReasonReadyToUnready = JobParameters.STOP_REASON_UNDEFINED;
|
||||||
|
|
||||||
/** Provide a handle to the service that this job will be run on. */
|
|
||||||
public int getServiceToken() {
|
|
||||||
return callingUid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core constructor for JobStatus instances. All other ctors funnel down to this one.
|
* Core constructor for JobStatus instances. All other ctors funnel down to this one.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user