Loading apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +49 −7 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.modules.expresslog.Histogram; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.job.controllers.JobStatus; import com.android.server.utils.AnrTimer; import java.util.Objects; Loading Loading @@ -319,6 +320,40 @@ public final class JobServiceContext implements ServiceConnection { } } // All instances of JobAnrTimer share the same arguments. private static final AnrTimer.Args sAnrTimerArgs = new AnrTimer.Args().enable(com.android.server.utils.Flags.anrTimerJobService()); /** * An AnrTimer for the JobServiceContext. There is one instance for each JobServiceContext * (these objects are not large). For convenience, simple no-argument methods are provided * which use 'this'. */ private class JobAnrTimer extends AnrTimer<JobCallback> { JobAnrTimer() { super(mCallbackHandler, MSG_TIMEOUT, "JobScheduler", sAnrTimerArgs); } public void start(long timeout) { start(mRunningCallback, /* pid */ 0, mRunningJob.getUid(), timeout); } public boolean cancel() { return cancel(mRunningCallback); } public void accept(TimeoutRecord tr) { accept(mRunningCallback, tr); } public boolean discard() { return discard(mRunningCallback); } } // The AnrTimer for this instance. private final JobAnrTimer mAnrTimer; JobServiceContext(JobSchedulerService service, JobConcurrencyManager concurrencyManager, JobNotificationCoordinator notificationCoordinator, IBatteryStats batteryStats, JobPackageTracker tracker, Looper looper) { Loading @@ -337,6 +372,7 @@ public final class JobServiceContext implements ServiceConnection { mAvailable = true; mVerb = VERB_FINISHED; mPreferredUid = NO_PREFERRED_UID; mAnrTimer = new JobAnrTimer(); } /** Loading Loading @@ -1177,6 +1213,7 @@ public final class JobServiceContext implements ServiceConnection { handleOpTimeoutLocked(); } else { JobCallback jc = (JobCallback)message.obj; mAnrTimer.discard(jc); StringBuilder sb = new StringBuilder(128); sb.append("Ignoring timeout of no longer active job"); if (jc.mStoppedReason != null) { Loading Loading @@ -1433,6 +1470,8 @@ public final class JobServiceContext implements ServiceConnection { mRunningJob.getUid())); break; case VERB_EXECUTING: // This is the tricky one. Some of banches here accept the timeout and some // discard it. if (mPendingStopReason != JobParameters.STOP_REASON_UNDEFINED) { if (mService.isReadyToBeExecutedLocked(mRunningJob, false)) { // Job became ready again while we were waiting to stop it (for example, Loading @@ -1447,6 +1486,7 @@ public final class JobServiceContext implements ServiceConnection { mParams.setStopReason(mPendingStopReason, mPendingInternalStopReason, mPendingDebugStopReason); sendStopMessageLocked(mPendingDebugStopReason); mAnrTimer.discard(); break; } } Loading Loading @@ -1481,6 +1521,7 @@ public final class JobServiceContext implements ServiceConnection { mParams.setStopReason(stopReason, internalStopReason, debugStopReason.toString()); sendStopMessageLocked(stopMessage.toString()); mAnrTimer.discard(); } else if (nowElapsed >= earliestStopTimeElapsed) { // We've given the app the minimum execution time. See if we should stop it or // let it continue running Loading Loading @@ -1522,6 +1563,7 @@ public final class JobServiceContext implements ServiceConnection { default: Slog.e(TAG, "Handling timeout for an invalid job state: " + getRunningJobNameLocked() + ", dropping."); mAnrTimer.discard(); closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout"); } } Loading Loading @@ -1565,9 +1607,12 @@ public final class JobServiceContext implements ServiceConnection { debugReason); } if (triggerAnr) { final TimeoutRecord tr = TimeoutRecord.forJobService(anrMessage); mAnrTimer.accept(tr); mActivityManagerInternal.appNotResponding( mRunningJob.serviceProcessName, mRunningJob.getUid(), TimeoutRecord.forJobService(anrMessage)); mRunningJob.serviceProcessName, mRunningJob.getUid(), tr); } else { mAnrTimer.discard(); } closeAndCleanupJobLocked(reschedule, debugReason); } Loading Loading @@ -1763,8 +1808,6 @@ public final class JobServiceContext implements ServiceConnection { * on with life. */ private void scheduleOpTimeOutLocked() { removeOpTimeOutLocked(); final long timeoutMillis; switch (mVerb) { case VERB_EXECUTING: Loading Loading @@ -1799,13 +1842,12 @@ public final class JobServiceContext implements ServiceConnection { mRunningJob.getServiceComponent().getShortClassName() + "' jId: " + mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s"); } Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT, mRunningCallback); mCallbackHandler.sendMessageDelayed(m, timeoutMillis); mAnrTimer.start(timeoutMillis); mTimeoutElapsed = sElapsedRealtimeClock.millis() + timeoutMillis; } private void removeOpTimeOutLocked() { mCallbackHandler.removeMessages(MSG_TIMEOUT); mAnrTimer.cancel(); } void dumpLocked(IndentingPrintWriter pw, final long nowElapsed) { Loading services/core/java/com/android/server/utils/AnrTimer.java +25 −4 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ import java.util.Objects; * * @hide */ public abstract class AnrTimer<V> implements AutoCloseable { public class AnrTimer<V> implements AutoCloseable { /** * The log tag. Loading Loading @@ -113,14 +113,18 @@ public abstract class AnrTimer<V> implements AutoCloseable { * is no valid pid available. * @return a valid pid or zero. */ public abstract int getPid(V obj); public int getPid(V obj) { return 0; } /** * Fetch the Linux uid from the object. The returned value may be zero to indicate that there * is no valid uid available. * @return a valid uid or zero. */ public abstract int getUid(V obj); public int getUid(V obj) { return 0; } /** * Return true if tracing is feature-enabled. This has no effect unless tracing is configured. Loading Loading @@ -437,6 +441,7 @@ public abstract class AnrTimer<V> implements AutoCloseable { /** Start a timer by sending a message to the client's handler. */ @Override void start(@NonNull V arg, int pid, int uid, long timeoutMs) { cancel(arg); final Message msg = mHandler.obtainMessage(mWhat, arg); mHandler.sendMessageDelayed(msg, timeoutMs); } Loading Loading @@ -667,8 +672,24 @@ public abstract class AnrTimer<V> implements AutoCloseable { * @param timeoutMs The timer timeout, in milliseconds. */ public void start(@NonNull V arg, long timeoutMs) { start(arg, getPid(arg), getUid(arg), timeoutMs); } /** * Start a timer associated with arg, pid, and uid. The same object must be used to cancel, * accept, or discard a timer later. If a timer already exists with the same arg, then the * existing timer is canceled and a new timer is created. The timeout is signed but negative * delays are nonsensical. Rather than throw an exception, timeouts less than 0ms are forced to * 0ms. This allows a client to deliver an immediate timeout via the AnrTimer. * * @param arg The key by which the timer is known. This is never examined or modified. * @param pid The process ID of the process that is being timed. * @param uid The UID of the process that is being timed. * @param timeoutMs The timer timeout, in milliseconds. */ public void start(@NonNull V arg, int pid, int uid, long timeoutMs) { if (timeoutMs < 0) timeoutMs = 0; mFeature.start(arg, getPid(arg), getUid(arg), timeoutMs); mFeature.start(arg, pid, uid, timeoutMs); } /** Loading services/core/java/com/android/server/utils/flags.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,11 @@ flag { description: "When true, start a trace if an ANR timer reaches 50%" bug: "352085328" } flag { name: "anr_timer_job_service" namespace: "system_performance" is_fixed_read_only: true description: "Use AnrTimer to signal ANRs in JobScheduler" bug: "408440679" } services/core/jni/com_android_server_utils_AnrTimer.cpp +0 −4 Original line number Diff line number Diff line Loading @@ -700,10 +700,6 @@ class AnrTimerService::Timer { if (extend && pid != 0) { initial.fill(pid); } // A zero-pid is odd but it means the upper layers will never ANR the process. Freezing // is always disabled. (It won't work anyway, but disabling it avoids error messages.) ALOGI_IF(DEBUG_ERROR && pid == 0, "error: zero-pid %s", toString().c_str()); } // Start a timer. This interface exists to generate log messages, if enabled. Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +49 −7 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.modules.expresslog.Histogram; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.job.controllers.JobStatus; import com.android.server.utils.AnrTimer; import java.util.Objects; Loading Loading @@ -319,6 +320,40 @@ public final class JobServiceContext implements ServiceConnection { } } // All instances of JobAnrTimer share the same arguments. private static final AnrTimer.Args sAnrTimerArgs = new AnrTimer.Args().enable(com.android.server.utils.Flags.anrTimerJobService()); /** * An AnrTimer for the JobServiceContext. There is one instance for each JobServiceContext * (these objects are not large). For convenience, simple no-argument methods are provided * which use 'this'. */ private class JobAnrTimer extends AnrTimer<JobCallback> { JobAnrTimer() { super(mCallbackHandler, MSG_TIMEOUT, "JobScheduler", sAnrTimerArgs); } public void start(long timeout) { start(mRunningCallback, /* pid */ 0, mRunningJob.getUid(), timeout); } public boolean cancel() { return cancel(mRunningCallback); } public void accept(TimeoutRecord tr) { accept(mRunningCallback, tr); } public boolean discard() { return discard(mRunningCallback); } } // The AnrTimer for this instance. private final JobAnrTimer mAnrTimer; JobServiceContext(JobSchedulerService service, JobConcurrencyManager concurrencyManager, JobNotificationCoordinator notificationCoordinator, IBatteryStats batteryStats, JobPackageTracker tracker, Looper looper) { Loading @@ -337,6 +372,7 @@ public final class JobServiceContext implements ServiceConnection { mAvailable = true; mVerb = VERB_FINISHED; mPreferredUid = NO_PREFERRED_UID; mAnrTimer = new JobAnrTimer(); } /** Loading Loading @@ -1177,6 +1213,7 @@ public final class JobServiceContext implements ServiceConnection { handleOpTimeoutLocked(); } else { JobCallback jc = (JobCallback)message.obj; mAnrTimer.discard(jc); StringBuilder sb = new StringBuilder(128); sb.append("Ignoring timeout of no longer active job"); if (jc.mStoppedReason != null) { Loading Loading @@ -1433,6 +1470,8 @@ public final class JobServiceContext implements ServiceConnection { mRunningJob.getUid())); break; case VERB_EXECUTING: // This is the tricky one. Some of banches here accept the timeout and some // discard it. if (mPendingStopReason != JobParameters.STOP_REASON_UNDEFINED) { if (mService.isReadyToBeExecutedLocked(mRunningJob, false)) { // Job became ready again while we were waiting to stop it (for example, Loading @@ -1447,6 +1486,7 @@ public final class JobServiceContext implements ServiceConnection { mParams.setStopReason(mPendingStopReason, mPendingInternalStopReason, mPendingDebugStopReason); sendStopMessageLocked(mPendingDebugStopReason); mAnrTimer.discard(); break; } } Loading Loading @@ -1481,6 +1521,7 @@ public final class JobServiceContext implements ServiceConnection { mParams.setStopReason(stopReason, internalStopReason, debugStopReason.toString()); sendStopMessageLocked(stopMessage.toString()); mAnrTimer.discard(); } else if (nowElapsed >= earliestStopTimeElapsed) { // We've given the app the minimum execution time. See if we should stop it or // let it continue running Loading Loading @@ -1522,6 +1563,7 @@ public final class JobServiceContext implements ServiceConnection { default: Slog.e(TAG, "Handling timeout for an invalid job state: " + getRunningJobNameLocked() + ", dropping."); mAnrTimer.discard(); closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout"); } } Loading Loading @@ -1565,9 +1607,12 @@ public final class JobServiceContext implements ServiceConnection { debugReason); } if (triggerAnr) { final TimeoutRecord tr = TimeoutRecord.forJobService(anrMessage); mAnrTimer.accept(tr); mActivityManagerInternal.appNotResponding( mRunningJob.serviceProcessName, mRunningJob.getUid(), TimeoutRecord.forJobService(anrMessage)); mRunningJob.serviceProcessName, mRunningJob.getUid(), tr); } else { mAnrTimer.discard(); } closeAndCleanupJobLocked(reschedule, debugReason); } Loading Loading @@ -1763,8 +1808,6 @@ public final class JobServiceContext implements ServiceConnection { * on with life. */ private void scheduleOpTimeOutLocked() { removeOpTimeOutLocked(); final long timeoutMillis; switch (mVerb) { case VERB_EXECUTING: Loading Loading @@ -1799,13 +1842,12 @@ public final class JobServiceContext implements ServiceConnection { mRunningJob.getServiceComponent().getShortClassName() + "' jId: " + mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s"); } Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT, mRunningCallback); mCallbackHandler.sendMessageDelayed(m, timeoutMillis); mAnrTimer.start(timeoutMillis); mTimeoutElapsed = sElapsedRealtimeClock.millis() + timeoutMillis; } private void removeOpTimeOutLocked() { mCallbackHandler.removeMessages(MSG_TIMEOUT); mAnrTimer.cancel(); } void dumpLocked(IndentingPrintWriter pw, final long nowElapsed) { Loading
services/core/java/com/android/server/utils/AnrTimer.java +25 −4 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ import java.util.Objects; * * @hide */ public abstract class AnrTimer<V> implements AutoCloseable { public class AnrTimer<V> implements AutoCloseable { /** * The log tag. Loading Loading @@ -113,14 +113,18 @@ public abstract class AnrTimer<V> implements AutoCloseable { * is no valid pid available. * @return a valid pid or zero. */ public abstract int getPid(V obj); public int getPid(V obj) { return 0; } /** * Fetch the Linux uid from the object. The returned value may be zero to indicate that there * is no valid uid available. * @return a valid uid or zero. */ public abstract int getUid(V obj); public int getUid(V obj) { return 0; } /** * Return true if tracing is feature-enabled. This has no effect unless tracing is configured. Loading Loading @@ -437,6 +441,7 @@ public abstract class AnrTimer<V> implements AutoCloseable { /** Start a timer by sending a message to the client's handler. */ @Override void start(@NonNull V arg, int pid, int uid, long timeoutMs) { cancel(arg); final Message msg = mHandler.obtainMessage(mWhat, arg); mHandler.sendMessageDelayed(msg, timeoutMs); } Loading Loading @@ -667,8 +672,24 @@ public abstract class AnrTimer<V> implements AutoCloseable { * @param timeoutMs The timer timeout, in milliseconds. */ public void start(@NonNull V arg, long timeoutMs) { start(arg, getPid(arg), getUid(arg), timeoutMs); } /** * Start a timer associated with arg, pid, and uid. The same object must be used to cancel, * accept, or discard a timer later. If a timer already exists with the same arg, then the * existing timer is canceled and a new timer is created. The timeout is signed but negative * delays are nonsensical. Rather than throw an exception, timeouts less than 0ms are forced to * 0ms. This allows a client to deliver an immediate timeout via the AnrTimer. * * @param arg The key by which the timer is known. This is never examined or modified. * @param pid The process ID of the process that is being timed. * @param uid The UID of the process that is being timed. * @param timeoutMs The timer timeout, in milliseconds. */ public void start(@NonNull V arg, int pid, int uid, long timeoutMs) { if (timeoutMs < 0) timeoutMs = 0; mFeature.start(arg, getPid(arg), getUid(arg), timeoutMs); mFeature.start(arg, pid, uid, timeoutMs); } /** Loading
services/core/java/com/android/server/utils/flags.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,11 @@ flag { description: "When true, start a trace if an ANR timer reaches 50%" bug: "352085328" } flag { name: "anr_timer_job_service" namespace: "system_performance" is_fixed_read_only: true description: "Use AnrTimer to signal ANRs in JobScheduler" bug: "408440679" }
services/core/jni/com_android_server_utils_AnrTimer.cpp +0 −4 Original line number Diff line number Diff line Loading @@ -700,10 +700,6 @@ class AnrTimerService::Timer { if (extend && pid != 0) { initial.fill(pid); } // A zero-pid is odd but it means the upper layers will never ANR the process. Freezing // is always disabled. (It won't work anyway, but disabling it avoids error messages.) ALOGI_IF(DEBUG_ERROR && pid == 0, "error: zero-pid %s", toString().c_str()); } // Start a timer. This interface exists to generate log messages, if enabled. Loading