diff options
| author | 2016-04-29 18:18:08 -0700 | |
|---|---|---|
| committer | 2016-05-03 11:48:25 -0700 | |
| commit | ef3aa6ee53c5e4f1c50dd5a9b5821c54e449d4b3 (patch) | |
| tree | e46b55c507aaba7ddb1a6f024a12b61a59798e49 | |
| parent | 344d23c0fadd9714453a2bfdebf1d1b304105acf (diff) | |
Fix issue #28477006: Add small event log to job scheduler
Added. Also fixed dumpsys output when filtering, to apply the
filter to (almost) all of the output.
Change-Id: Iafb446599ad8fddbe8a766784deff618a6cfdbb7
13 files changed, 176 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 6a08191eef47..6b0ead47923b 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -309,8 +309,8 @@ public class DeviceIdleController extends SystemService private static final int EVENT_DEEP_IDLE = 4; private static final int EVENT_DEEP_MAINTENANCE = 5; - private int[] mEventCmds = new int[EVENT_BUFFER_SIZE]; - private long[] mEventTimes = new long[EVENT_BUFFER_SIZE]; + private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE]; + private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE]; private void addEvent(int cmd) { if (mEventCmds[0] != cmd) { diff --git a/services/core/java/com/android/server/job/JobCompletedListener.java b/services/core/java/com/android/server/job/JobCompletedListener.java index a7af9cd2b64b..655abd73e6ad 100644 --- a/services/core/java/com/android/server/job/JobCompletedListener.java +++ b/services/core/java/com/android/server/job/JobCompletedListener.java @@ -23,10 +23,9 @@ import com.android.server.job.controllers.JobStatus; * {@link com.android.server.job.JobSchedulerService}. */ public interface JobCompletedListener { - /** * Callback for when a job is completed. * @param needsReschedule Whether the implementing class should reschedule this job. */ - public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule); + void onJobCompleted(JobStatus jobStatus, boolean needsReschedule); } diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java index e5a20954dcc2..4ba9dae87ca4 100644 --- a/services/core/java/com/android/server/job/JobPackageTracker.java +++ b/services/core/java/com/android/server/job/JobPackageTracker.java @@ -33,6 +33,28 @@ public final class JobPackageTracker { // Number of historical data sets we keep. static final int NUM_HISTORY = 5; + private static final int EVENT_BUFFER_SIZE = 50; + + public static final int EVENT_NULL = 0; + public static final int EVENT_START_JOB = 1; + public static final int EVENT_STOP_JOB = 2; + + private int[] mEventCmds = new int[EVENT_BUFFER_SIZE]; + private long[] mEventTimes = new long[EVENT_BUFFER_SIZE]; + private int[] mEventUids = new int[EVENT_BUFFER_SIZE]; + private String[] mEventTags = new String[EVENT_BUFFER_SIZE]; + + public void addEvent(int cmd, int uid, String tag) { + System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1); + System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1); + System.arraycopy(mEventUids, 0, mEventUids, 1, EVENT_BUFFER_SIZE - 1); + System.arraycopy(mEventTags, 0, mEventTags, 1, EVENT_BUFFER_SIZE - 1); + mEventCmds[0] = cmd; + mEventTimes[0] = SystemClock.elapsedRealtime(); + mEventUids[0] = uid; + mEventTags[0] = tag; + } + DataSet mCurDataSet = new DataSet(); DataSet[] mLastDataSets = new DataSet[NUM_HISTORY]; @@ -240,7 +262,8 @@ public final class JobPackageTracker { } } - void dump(PrintWriter pw, String header, String prefix, long now, long nowEllapsed) { + void dump(PrintWriter pw, String header, String prefix, long now, long nowEllapsed, + int filterUid) { final long period = getTotalTime(now); pw.print(prefix); pw.print(header); pw.print(" at "); pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartClockTime).toString()); @@ -251,12 +274,16 @@ public final class JobPackageTracker { pw.println(":"); final int NE = mEntries.size(); for (int i = 0; i < NE; i++) { + int uid = mEntries.keyAt(i); + if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) { + continue; + } ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i); final int NP = uidMap.size(); for (int j = 0; j < NP; j++) { PackageEntry pe = uidMap.valueAt(j); pw.print(prefix); pw.print(" "); - UserHandle.formatUid(pw, mEntries.keyAt(i)); + UserHandle.formatUid(pw, uid); pw.print(" / "); pw.print(uidMap.keyAt(j)); pw.print(":"); printDuration(pw, period, pe.getPendingTime(now), "pending"); @@ -309,6 +336,7 @@ public final class JobPackageTracker { } else { mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now); } + addEvent(EVENT_START_JOB, job.getSourceUid(), job.getBatteryName()); } public void noteInactive(JobStatus job) { @@ -319,6 +347,7 @@ public final class JobPackageTracker { mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now); } rebatchIfNeeded(now); + addEvent(EVENT_STOP_JOB, job.getSourceUid(), job.getBatteryName()); } public float getLoadFactor(JobStatus job) { @@ -339,7 +368,7 @@ public final class JobPackageTracker { return time / (float)period; } - public void dump(PrintWriter pw, String prefix) { + public void dump(PrintWriter pw, String prefix, int filterUid) { final long now = SystemClock.uptimeMillis(); final long nowEllapsed = SystemClock.elapsedRealtime(); final DataSet total; @@ -352,10 +381,43 @@ public final class JobPackageTracker { mCurDataSet.addTo(total, now); for (int i = 1; i < mLastDataSets.length; i++) { if (mLastDataSets[i] != null) { - mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowEllapsed); + mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowEllapsed, filterUid); pw.println(); } } - total.dump(pw, "Current stats", prefix, now, nowEllapsed); + total.dump(pw, "Current stats", prefix, now, nowEllapsed, filterUid); + } + + public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) { + if (mEventCmds[0] == EVENT_NULL) { + return false; + } + pw.println(" Job history:"); + long now = SystemClock.elapsedRealtime(); + for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) { + int uid = mEventUids[i]; + if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) { + continue; + } + int cmd = mEventCmds[i]; + if (cmd == EVENT_NULL) { + continue; + } + String label; + switch (mEventCmds[i]) { + case EVENT_START_JOB: label = "START"; break; + case EVENT_STOP_JOB: label = " STOP"; break; + default: label = " ??"; break; + } + pw.print(prefix); + TimeUtils.formatDuration(mEventTimes[i]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN); + pw.print(" "); + pw.print(label); + pw.print(": "); + UserHandle.formatUid(pw, uid); + pw.print(" "); + pw.println(mEventTags[i]); + } + return true; } } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 075a88f34ac9..7e26d4b5c4ca 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -1477,17 +1477,45 @@ public final class JobSchedulerService extends com.android.server.SystemService return s.toString(); } + static void dumpHelp(PrintWriter pw) { + pw.println("Job Scheduler (jobscheduler) dump options:"); + pw.println(" [-h] [package] ..."); + pw.println(" -h: print this help"); + pw.println(" [package] is an optional package name to limit the output to."); + } + void dumpInternal(final PrintWriter pw, String[] args) { int filterUid = -1; if (!ArrayUtils.isEmpty(args)) { - try { - filterUid = getContext().getPackageManager().getPackageUid(args[0], - PackageManager.MATCH_UNINSTALLED_PACKAGES); - } catch (NameNotFoundException ignored) { + int opti = 0; + while (opti < args.length) { + String arg = args[opti]; + if ("-h".equals(arg)) { + dumpHelp(pw); + return; + } else if ("-a".equals(arg)) { + // Ignore, we always dump all. + } else if (arg.length() > 0 && arg.charAt(0) == '-') { + pw.println("Unknown option: " + arg); + return; + } else { + break; + } + opti++; + } + if (opti < args.length) { + String pkg = args[opti]; + try { + filterUid = getContext().getPackageManager().getPackageUid(pkg, + PackageManager.MATCH_UNINSTALLED_PACKAGES); + } catch (NameNotFoundException ignored) { + pw.println("Invalid package: " + pkg); + return; + } } } - final int filterUidFinal = filterUid; + final int filterUidFinal = UserHandle.getAppId(filterUid); final long now = SystemClock.elapsedRealtime(); synchronized (mLock) { pw.println("Started users: " + Arrays.toString(mStartedUsers)); @@ -1502,8 +1530,7 @@ public final class JobSchedulerService extends com.android.server.SystemService pw.println(job.toShortString()); // Skip printing details if the caller requested a filter - if (filterUidFinal != -1 && job.getUid() != filterUidFinal - && job.getSourceUid() != filterUidFinal) { + if (!job.shouldDump(filterUidFinal)) { return; } @@ -1526,17 +1553,23 @@ public final class JobSchedulerService extends com.android.server.SystemService } for (int i=0; i<mControllers.size(); i++) { pw.println(); - mControllers.get(i).dumpControllerStateLocked(pw); + mControllers.get(i).dumpControllerStateLocked(pw, filterUidFinal); } pw.println(); pw.println("Uid priority overrides:"); for (int i=0; i< mUidPriorityOverride.size(); i++) { - pw.print(" "); pw.print(UserHandle.formatUid(mUidPriorityOverride.keyAt(i))); - pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i)); + int uid = mUidPriorityOverride.keyAt(i); + if (filterUidFinal == -1 || filterUidFinal == UserHandle.getAppId(uid)) { + pw.print(" "); pw.print(UserHandle.formatUid(uid)); + pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i)); + } } pw.println(); - mJobPackageTracker.dump(pw, ""); + mJobPackageTracker.dump(pw, "", filterUidFinal); pw.println(); + if (mJobPackageTracker.dumpHistory(pw, "", filterUidFinal)) { + pw.println(); + } pw.println("Pending queue:"); for (int i=0; i<mPendingJobs.size(); i++) { JobStatus job = mPendingJobs.get(i); @@ -1571,10 +1604,12 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } - pw.println(); - pw.print("mReadyToRock="); pw.println(mReadyToRock); - pw.print("mReportedActive="); pw.println(mReportedActive); - pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs); + if (filterUid == -1) { + pw.println(); + pw.print("mReadyToRock="); pw.println(mReadyToRock); + pw.print("mReportedActive="); pw.println(mReportedActive); + pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs); + } } pw.println(); } diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java index 02bc36ca5c10..759303542aec 100644 --- a/services/core/java/com/android/server/job/controllers/AppIdleController.java +++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java @@ -23,10 +23,8 @@ import android.util.Slog; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerService; import com.android.server.job.JobStore; -import com.android.server.job.StateChangedListener; import java.io.PrintWriter; -import java.util.ArrayList; /** * Controls when apps are considered idle and if jobs pertaining to those apps should @@ -123,11 +121,15 @@ public class AppIdleController extends StateController { } @Override - public void dumpControllerStateLocked(final PrintWriter pw) { + public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) { pw.println("AppIdle"); pw.println("Parole On: " + mAppIdleParoleOn); mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() { @Override public void process(JobStatus jobStatus) { + // Skip printing details if the caller requested a filter + if (!jobStatus.shouldDump(filterUid)) { + return; + } pw.print(" "); pw.print(jobStatus.getSourcePackageName()); pw.print(": runnable="); diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java index 077236443dea..a0cb25fb6870 100644 --- a/services/core/java/com/android/server/job/controllers/BatteryController.java +++ b/services/core/java/com/android/server/job/controllers/BatteryController.java @@ -194,15 +194,21 @@ public class BatteryController extends StateController { } @Override - public void dumpControllerStateLocked(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { pw.println("Batt."); pw.println("Stable power: " + mChargeTracker.isOnStablePower()); Iterator<JobStatus> it = mTrackedTasks.iterator(); if (it.hasNext()) { - pw.print(String.valueOf(it.next().hashCode())); + JobStatus jobStatus = it.next(); + if (jobStatus.shouldDump(filterUid)) { + pw.print(String.valueOf(jobStatus.hashCode())); + } } while (it.hasNext()) { - pw.print("," + String.valueOf(it.next().hashCode())); + JobStatus jobStatus = it.next(); + if (jobStatus.shouldDump(filterUid)) { + pw.print("," + String.valueOf(jobStatus.hashCode())); + } } pw.println(); } diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index f5aac087f9b0..9fd22686a9a0 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -181,14 +181,16 @@ public class ConnectivityController extends StateController implements }; @Override - public void dumpControllerStateLocked(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { pw.println("Conn."); for (int i = 0; i < mTrackedJobs.size(); i++) { final JobStatus js = mTrackedJobs.get(i); - pw.println(String.valueOf(js.getJobId() + "," + js.getUid()) - + ": C=" + js.hasConnectivityConstraint() - + ", UM=" + js.hasUnmeteredConstraint() - + ", NR=" + js.hasNotRoamingConstraint()); + if (js.shouldDump(filterUid)) { + pw.println(String.valueOf(js.getJobId() + "," + js.getUid()) + + ": C=" + js.hasConnectivityConstraint() + + ", UM=" + js.hasUnmeteredConstraint() + + ", NR=" + js.hasNotRoamingConstraint()); + } } } } diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java index c5b1a3d88052..6722bfbeb0c0 100644 --- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java +++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java @@ -322,11 +322,15 @@ public class ContentObserverController extends StateController { } @Override - public void dumpControllerStateLocked(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { pw.println("Content."); boolean printed = false; Iterator<JobStatus> it = mTrackedTasks.iterator(); while (it.hasNext()) { + JobStatus js = it.next(); + if (!js.shouldDump(filterUid)) { + continue; + } if (!printed) { pw.print(" "); printed = true; @@ -343,13 +347,24 @@ public class ContentObserverController extends StateController { pw.println(" Observers:"); for (int i = 0; i < N; i++) { ObserverInstance obs = mObservers.valueAt(i); + int M = obs.mJobs.size(); + boolean shouldDump = false; + for (int j=0; j<M; j++) { + JobInstance inst = obs.mJobs.valueAt(j); + if (inst.mJobStatus.shouldDump(filterUid)) { + shouldDump = true; + break; + } + } + if (!shouldDump) { + continue; + } pw.print(" "); pw.print(mObservers.keyAt(i)); pw.print(" ("); pw.print(System.identityHashCode(obs)); pw.println("):"); pw.println(" Jobs:"); - int M = obs.mJobs.size(); for (int j=0; j<M; j++) { JobInstance inst = obs.mJobs.valueAt(j); pw.print(" "); diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java index fe563d230450..345a032497ef 100644 --- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java +++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java @@ -29,10 +29,8 @@ import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerService; import com.android.server.job.JobStore; -import com.android.server.job.StateChangedListener; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.Arrays; /** @@ -175,10 +173,13 @@ public class DeviceIdleJobsController extends StateController { } @Override - public void dumpControllerStateLocked(final PrintWriter pw) { + public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) { pw.println("DeviceIdleJobsController"); mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() { @Override public void process(JobStatus jobStatus) { + if (!jobStatus.shouldDump(filterUid)) { + return; + } pw.print(" "); pw.print(jobStatus.getSourcePackageName()); pw.print(": runnable="); diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java index 50aa88257ace..c7a679cc4697 100644 --- a/services/core/java/com/android/server/job/controllers/IdleController.java +++ b/services/core/java/com/android/server/job/controllers/IdleController.java @@ -190,12 +190,15 @@ public class IdleController extends StateController { } @Override - public void dumpControllerStateLocked(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { pw.print("Idle: "); pw.println(mIdleTracker.isIdle() ? "true" : "false"); pw.println(mTrackedTasks.size()); for (int i = 0; i < mTrackedTasks.size(); i++) { final JobStatus js = mTrackedTasks.get(i); + if (!js.shouldDump(filterUid)) { + continue; + } pw.print(" "); pw.print(String.valueOf(js.getJobId() + "," + js.getUid())); pw.println(".."); diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index 19bede97c503..072787b19dc5 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -410,6 +410,11 @@ public final class JobStatus { return true; } + public boolean shouldDump(int filterUid) { + return filterUid == -1 || UserHandle.getAppId(getUid()) == filterUid + || UserHandle.getAppId(getSourceUid()) == filterUid; + } + /** * @return Whether or not this job is ready to run, based on its requirements. This is true if * the constraints are satisfied <strong>or</strong> the deadline on the job has expired. 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 013903939f18..1721fb9ac3fc 100644 --- a/services/core/java/com/android/server/job/controllers/StateController.java +++ b/services/core/java/com/android/server/job/controllers/StateController.java @@ -64,5 +64,5 @@ public abstract class StateController { public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) { } - public abstract void dumpControllerStateLocked(PrintWriter pw); + public abstract void dumpControllerStateLocked(PrintWriter pw, int filterUid); } 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 ab6768e99878..2f8ca7eb1f80 100644 --- a/services/core/java/com/android/server/job/controllers/TimeController.java +++ b/services/core/java/com/android/server/job/controllers/TimeController.java @@ -275,7 +275,7 @@ public class TimeController extends StateController { }; @Override - public void dumpControllerStateLocked(PrintWriter pw) { + public void dumpControllerStateLocked(PrintWriter pw, int filterUid) { final long nowElapsed = SystemClock.elapsedRealtime(); pw.println("Alarms (" + SystemClock.elapsedRealtime() + ")"); pw.println( @@ -284,6 +284,9 @@ public class TimeController extends StateController { + "s"); pw.println("Tracking:"); for (JobStatus ts : mTrackedJobs) { + if (!ts.shouldDump(filterUid)) { + continue; + } pw.println(String.valueOf(ts.getJobId() + "," + ts.getUid()) + ": (" + (ts.hasTimingDelayConstraint() ? ts.getEarliestRunTime() : "N/A") + ", " + (ts.hasDeadlineConstraint() ?ts.getLatestRunTimeElapsed() : "N/A") |