From 822cbd130fb6c5016c328a9e85b27eb024aef229 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 25 Feb 2016 11:09:55 -0700 Subject: [PATCH] Fix JobSchedulerService FBE regression. Internally isReadyToBeExecutedLocked() needs to check if the target service is actually present and runnable. For example, when an FBE device is locked, we need to keep any encryption-unaware jobs pending until the device is later unlocked. Bug: 26279465 Change-Id: I53ff4a2243ebe8a199d0e8dcf87dc3f5b06a2686 --- .../server/job/JobSchedulerService.java | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 42ecc06605ff3..b30afb5e4777e 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -19,6 +19,7 @@ package com.android.server.job; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -53,6 +54,7 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.app.IBatteryStats; +import com.android.internal.util.ArrayUtils; import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.android.server.job.JobStore.JobStatusFunctor; @@ -65,6 +67,8 @@ import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.StateController; import com.android.server.job.controllers.TimeController; +import libcore.util.EmptyArray; + /** * Responsible for taking jobs representing work to be performed by a client app, and determining * based on the criteria specified when that job should be run against the client application's @@ -139,7 +143,7 @@ public final class JobSchedulerService extends com.android.server.SystemService */ final ArrayList mPendingJobs = new ArrayList<>(); - final ArrayList mStartedUsers = new ArrayList<>(); + int[] mStartedUsers = EmptyArray.INT; final JobHandler mHandler; final JobSchedulerStub mJobSchedulerStub; @@ -218,14 +222,20 @@ public final class JobSchedulerService extends com.android.server.SystemService @Override public void onStartUser(int userHandle) { - mStartedUsers.add(userHandle); + mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userHandle); + // Let's kick any outstanding jobs for this user. + mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); + } + + @Override + public void onUnlockUser(int userHandle) { // Let's kick any outstanding jobs for this user. mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); } @Override public void onStopUser(int userHandle) { - mStartedUsers.remove(Integer.valueOf(userHandle)); + mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle); } /** @@ -905,18 +915,31 @@ public final class JobSchedulerService extends com.android.server.SystemService * - It's not pending. * - It's not already running on a JSC. * - The user that requested the job is running. + * - The component is enabled and runnable. */ private boolean isReadyToBeExecutedLocked(JobStatus job) { final boolean jobReady = job.isReady(); final boolean jobPending = mPendingJobs.contains(job); final boolean jobActive = isCurrentlyActiveLocked(job); - final boolean userRunning = mStartedUsers.contains(job.getUserId()); + + final int userId = job.getUserId(); + final boolean userStarted = ArrayUtils.contains(mStartedUsers, userId); + final boolean componentPresent; + try { + componentPresent = (AppGlobals.getPackageManager().getServiceInfo( + job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, + userId) != null); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + if (DEBUG) { Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() + " ready=" + jobReady + " pending=" + jobPending - + " active=" + jobActive + " userRunning=" + userRunning); + + " active=" + jobActive + " userStarted=" + userStarted + + " componentPresent=" + componentPresent); } - return userRunning && jobReady && !jobPending && !jobActive; + return userStarted && componentPresent && jobReady && !jobPending && !jobActive; } /** @@ -1251,11 +1274,7 @@ public final class JobSchedulerService extends com.android.server.SystemService void dumpInternal(final PrintWriter pw) { final long now = SystemClock.elapsedRealtime(); synchronized (mLock) { - pw.print("Started users: "); - for (int i=0; i 0) { mJobs.forEachJob(new JobStatusFunctor() { @@ -1275,7 +1294,7 @@ public final class JobSchedulerService extends com.android.server.SystemService pw.print(" active="); pw.print(isCurrentlyActiveLocked(job)); pw.print(" user="); - pw.print(mStartedUsers.contains(job.getUserId())); + pw.print(ArrayUtils.contains(mStartedUsers, job.getUserId())); pw.println(")"); } });