Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 822cbd13 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

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
parent 6bda33f6
Loading
Loading
Loading
Loading
+31 −12
Original line number Diff line number Diff line
@@ -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<JobStatus> mPendingJobs = new ArrayList<>();

    final ArrayList<Integer> 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<mStartedUsers.size(); i++) {
                pw.print("u" + mStartedUsers.get(i) + " ");
            }
            pw.println();
            pw.println("Started users: " + Arrays.toString(mStartedUsers));
            pw.println("Registered jobs:");
            if (mJobs.size() > 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(")");
                    }
                });