diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index b0d76e854af23..b8fe88439c2d8 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -524,7 +524,7 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "Removing jobs for package " + pkgName + " in user " + userId); } - cancelJobsForUid(pkgUid); + cancelJobsForUid(pkgUid, "app package state changed"); } } catch (RemoteException|IllegalArgumentException e) { /* @@ -553,7 +553,7 @@ public final class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "Removing jobs for uid: " + uidRemoved); } - cancelJobsForUid(uidRemoved); + cancelJobsForUid(uidRemoved, "app uninstalled"); } } else if (Intent.ACTION_USER_REMOVED.equals(action)) { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); @@ -611,7 +611,7 @@ public final class JobSchedulerService extends com.android.server.SystemService @Override public void onUidGone(int uid, boolean disabled) throws RemoteException { updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); if (disabled) { - cancelJobsForUid(uid); + cancelJobsForUid(uid, "uid gone"); } } @@ -620,7 +620,7 @@ public final class JobSchedulerService extends com.android.server.SystemService @Override public void onUidIdle(int uid, boolean disabled) throws RemoteException { if (disabled) { - cancelJobsForUid(uid); + cancelJobsForUid(uid, "app uid idle"); } } }; @@ -689,7 +689,7 @@ public final class JobSchedulerService extends com.android.server.SystemService jobStatus.prepareLocked(ActivityManager.getService()); if (toCancel != null) { - cancelJobImplLocked(toCancel, jobStatus); + cancelJobImplLocked(toCancel, jobStatus, "job rescheduled by app"); } if (work != null) { // If work has been supplied, enqueue it into the new job. @@ -747,7 +747,7 @@ public final class JobSchedulerService extends com.android.server.SystemService final List jobsForUser = mJobs.getJobsByUser(userHandle); for (int i=0; i= 0; i--) { final JobStatus job = jobsForUid.get(i); if (job.getSourcePackageName().equals(pkgName)) { - cancelJobImplLocked(job, null); + cancelJobImplLocked(job, null, "app force stopped"); } } } @@ -778,12 +778,12 @@ public final class JobSchedulerService extends com.android.server.SystemService * @param uid Uid to check against for removal of a job. * */ - public void cancelJobsForUid(int uid) { + public void cancelJobsForUid(int uid, String reason) { synchronized (mLock) { final List jobsForUid = mJobs.getJobsByUid(uid); for (int i=0; i Error * _PENDING -> Error */ - private void handleFinishedLocked(boolean reschedule) { + private void handleFinishedLocked(boolean reschedule, String reason) { switch (mVerb) { case VERB_EXECUTING: case VERB_STOPPING: - closeAndCleanupJobLocked(reschedule); + closeAndCleanupJobLocked(reschedule, reason); break; default: Slog.e(TAG, "Got an execution complete message for a job that wasn't being" + @@ -544,7 +564,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * in the message queue. * _ENDING -> No point in doing anything here, so we ignore. */ - private void handleCancelLocked() { + private void handleCancelLocked(String reason) { if (JobSchedulerService.DEBUG) { Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " " + VERB_STRINGS[mVerb]); @@ -553,9 +573,10 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne case VERB_BINDING: case VERB_STARTING: mCancelled = true; + applyStoppedReasonLocked(reason); break; case VERB_EXECUTING: - sendStopMessageLocked(); + sendStopMessageLocked(reason); break; case VERB_STOPPING: // Nada. @@ -572,7 +593,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne case VERB_BINDING: Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + ", dropping."); - closeAndCleanupJobLocked(false /* needsReschedule */); + closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while binding"); break; case VERB_STARTING: // Client unresponsive - wedged or failed to respond in time. We don't really @@ -580,25 +601,25 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne // FINISHED/NO-RETRY. Slog.e(TAG, "No response from client for onStartJob '" + mRunningJob.toShortString()); - closeAndCleanupJobLocked(false /* needsReschedule */); + closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while starting"); break; case VERB_STOPPING: // At least we got somewhere, so fail but ask the JobScheduler to reschedule. Slog.e(TAG, "No response from client for onStopJob, '" + mRunningJob.toShortString()); - closeAndCleanupJobLocked(true /* needsReschedule */); + closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping"); break; case VERB_EXECUTING: // Not an error - client ran out of time. Slog.i(TAG, "Client timed out while executing (no jobFinished received)." + " sending onStop. " + mRunningJob.toShortString()); mParams.setStopReason(JobParameters.REASON_TIMEOUT); - sendStopMessageLocked(); + sendStopMessageLocked("timeout while executing"); break; default: Slog.e(TAG, "Handling timeout for an invalid job state: " + mRunningJob.toShortString() + ", dropping."); - closeAndCleanupJobLocked(false /* needsReschedule */); + closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout"); } } @@ -606,11 +627,11 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING -> * VERB_STOPPING. */ - private void sendStopMessageLocked() { + private void sendStopMessageLocked(String reason) { removeOpTimeOutLocked(); if (mVerb != VERB_EXECUTING) { Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob); - closeAndCleanupJobLocked(false /* reschedule */); + closeAndCleanupJobLocked(false /* reschedule */, reason); return; } try { @@ -620,7 +641,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } catch (RemoteException e) { Slog.e(TAG, "Error sending onStopJob to client.", e); // The job's host app apparently crashed during the job, so we should reschedule. - closeAndCleanupJobLocked(true /* reschedule */); + closeAndCleanupJobLocked(true /* reschedule */, "host crashed when trying to stop"); } } @@ -630,11 +651,12 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * or from acknowledging the stop message we sent. Either way, we're done tracking it and * we want to clean up internally. */ - private void closeAndCleanupJobLocked(boolean reschedule) { + private void closeAndCleanupJobLocked(boolean reschedule, String reason) { final JobStatus completedJob; if (mVerb == VERB_FINISHED) { return; } + applyStoppedReasonLocked(reason); completedJob = mRunningJob; mJobPackageTracker.noteInactive(completedJob); try { @@ -658,6 +680,13 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne mCompletedListener.onJobCompletedLocked(completedJob, reschedule); } + private void applyStoppedReasonLocked(String reason) { + if (reason != null && mStoppedReason == null) { + mStoppedReason = reason; + mStoppedTime = SystemClock.elapsedRealtime(); + } + } + /** * Called when sending a message to the client, over whose execution we have no control. If * we haven't received a response in a certain amount of time, we want to give up and carry