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

Commit 12eec234 authored by Matthew Williams's avatar Matthew Williams Committed by Android (Google) Code Review
Browse files

Merge "JobScheduler only run jobs for started users." into lmp-dev

parents d9a218d4 9ae3dbee
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@ import android.os.PersistableBundle;
 * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the
 * parameters required to schedule work against the calling application. These are constructed
 * using the {@link JobInfo.Builder}.
 * You must specify at least one sort of constraint on the JobInfo object that you are creating.
 * The goal here is to provide the scheduler with high-level semantics about the work you want to
 * accomplish. Doing otherwise with throw an exception in your app.
 */
public class JobInfo implements Parcelable {
    public interface NetworkType {
@@ -434,7 +437,7 @@ public class JobInfo implements Parcelable {
         * @return The job object to hand to the JobScheduler. This object is immutable.
         */
        public JobInfo build() {
            // Allow tasks with no constraints. What am I, a database?
            // Allow jobs with no constraints - What am I, a database?
            if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
                    !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) {
                throw new IllegalArgumentException("You're trying to build a job with no " +
+31 −1
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ public class JobSchedulerService extends com.android.server.SystemService
     */
    final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>();

    final ArrayList<Integer> mStartedUsers = new ArrayList();

    final JobHandler mHandler;
    final JobSchedulerStub mJobSchedulerStub;

@@ -151,6 +153,18 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    };

    @Override
    public void onStartUser(int userHandle) {
        mStartedUsers.add(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));
    }

    /**
     * Entry point from client to schedule the provided job.
     * This cancels the job if it's already been scheduled, and replaces it with the one provided.
@@ -610,9 +624,20 @@ public class JobSchedulerService extends com.android.server.SystemService
         *      - It's ready.
         *      - It's not pending.
         *      - It's not already running on a JSC.
         *      - The user that requested the job is running.
         */
        private boolean isReadyToBeExecutedLocked(JobStatus job) {
              return job.isReady() && !mPendingJobs.contains(job) && !isCurrentlyActiveLocked(job);
            final boolean jobReady = job.isReady();
            final boolean jobPending = mPendingJobs.contains(job);
            final boolean jobActive = isCurrentlyActiveLocked(job);
            final boolean userRunning = mStartedUsers.contains(job.getUserId());

            if (DEBUG) {
                Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
                        + " ready=" + jobReady + " pending=" + jobPending
                        + " active=" + jobActive + " userRunning=" + userRunning);
            }
            return userRunning && jobReady && !jobPending && !jobActive;
        }

        /**
@@ -795,6 +820,11 @@ public class JobSchedulerService extends com.android.server.SystemService

    void dumpInternal(PrintWriter pw) {
        synchronized (mJobs) {
            pw.print("Started users: ");
            for (int i=0; i<mStartedUsers.size(); i++) {
                pw.print("u" + mStartedUsers.get(i) + " ");
            }
            pw.println();
            pw.println("Registered jobs:");
            if (mJobs.size() > 0) {
                ArraySet<JobStatus> jobs = mJobs.getJobs();
+30 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.os.PersistableBundle;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateUtils;

import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -41,6 +42,7 @@ public class JobStatus {
    public static final long NO_EARLIEST_RUNTIME = 0L;

    final JobInfo job;
    /** Uid of the package requesting this job. */
    final int uId;
    final String name;
    final String tag;
@@ -214,12 +216,39 @@ public class JobStatus {
        return String.valueOf(hashCode()).substring(0, 3) + ".."
                + ":[" + job.getService()
                + ",jId=" + job.getId()
                + ",R=(" + earliestRunTimeElapsedMillis + "," + latestRunTimeElapsedMillis + ")"
                + ",u" + getUserId()
                + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
                + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
                + ",N=" + job.getNetworkCapabilities() + ",C=" + job.isRequireCharging()
                + ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures
                + ",P=" + job.isPersisted()
                + (isReady() ? "(READY)" : "")
                + "]";
    }

    private String formatRunTime(long runtime, long  defaultValue) {
        if (runtime == defaultValue) {
            return "none";
        } else {
            long elapsedNow = SystemClock.elapsedRealtime();
            long nextRuntime = runtime - elapsedNow;
            if (nextRuntime > 0) {
                return DateUtils.formatElapsedTime(nextRuntime / 1000);
            } else {
                return "-" + DateUtils.formatElapsedTime(nextRuntime / -1000);
            }
        }
    }

    /**
     * Convenience function to identify a job uniquely without pulling all the data that
     * {@link #toString()} returns.
     */
    public String toShortString() {
        return job.getService().flattenToShortString() + " jId=" + job.getId() +
                ", u" + getUserId();
    }

    // Dumpsys infrastructure
    public void dump(PrintWriter pw, String prefix) {
        pw.println(this.toString());
+14 −0
Original line number Diff line number Diff line
@@ -141,6 +141,20 @@
                        android:id="@+id/checkbox_idle"
                        android:text="@string/idle_mode_text"/>
                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/persisted_caption"
                        android:layout_marginRight="15dp"/>
                    <CheckBox
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:id="@+id/checkbox_persisted"
                        android:text="@string/persisted_mode_text"/>
                </LinearLayout>

            </LinearLayout>
        <Button
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ limitations under the License.
    <string name="charging_caption">Charging:</string>
    <string name="charging_text">Requires device plugged in.</string>
    <string name="idle_caption">Idle:</string>
    <string name="persisted_caption">Persisted:</string>
    <string name="constraints">Constraints</string>
    <string name="connectivity">Connectivity:</string>
    <string name="any">Any</string>
@@ -34,4 +35,5 @@ limitations under the License.
    <string name="timing">Timing:</string>
    <string name="delay">Delay:</string>
    <string name="deadline">Deadline:</string>
    <string name="persisted_mode_text">Persisted:</string>
</resources>
Loading