remove possible JobScheduler race in cancel()

Client can jobFinished() before getting a cancel msg.
1) Do better clean up of JobServiceContext after client jobFinished()
to remove superfluous MSG_CANCELs
2) When processing MSG_CANCEL check whether the context is still active
3) Do JobServiceContext cleanup before calling back to JobSchedulerService
Client can get a cancel msg even after calling jobFinished() (opposite to above)
1) explicitly check whether there are any MSG_CALLBACKs in the queue before
processing a MSG_CANCEL. If there are we can throw away the cancel.

Bug: 16547638
Change-Id: I90644586c7895a9ce97de752a5d657faf7f74b78
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 587f596..9ac90dc 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -224,6 +224,9 @@
     }
 
     private void cancelJobLocked(JobStatus cancelled) {
+        if (DEBUG) {
+            Slog.d(TAG, "Cancelling: " + cancelled);
+        }
         // Remove from store.
         stopTrackingJob(cancelled);
         // Remove from pending queue.
@@ -447,8 +450,7 @@
         }
         if (!stopTrackingJob(jobStatus)) {
             if (DEBUG) {
-                Slog.e(TAG, "Error removing job: could not find job to remove. Was job " +
-                        "removed while executing?");
+                Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
             }
             return;
         }
@@ -611,7 +613,7 @@
                         final JobStatus running = jsc.getRunningJob();
                         if (running != null && running.matches(nextPending.getUid(),
                                 nextPending.getJobId())) {
-                            // Already running this tId for this uId, skip.
+                            // Already running this job for this uId, skip.
                             availableContext = null;
                             break;
                         }
@@ -691,7 +693,7 @@
         @Override
         public int schedule(JobInfo job) throws RemoteException {
             if (DEBUG) {
-                Slog.d(TAG, "Scheduling job: " + job);
+                Slog.d(TAG, "Scheduling job: " + job.toString());
             }
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();