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

Commit a06ec6a9 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add new job scheduler constraints for "battery not low".

Clean up the implementation of boolean constraints so that
they are in a single flags value that gets propagated all of
the way from JobInfo.Builder in to the JobStatus.  Much simpler
and easier to add new constraints!

Also introduce some shell commands to make it easier to write
tests against the job scheduler (and other things tied to power).
One of the big things here is that there is a new sequence number
that propagates with battery updates, which we can look for in
the job scheduler to determine when a change the test has made
to battery state has actually gotten applied, to allow it to
safely and minimally wait until executing the condition being
tested.

Test: New BatteryConstraintTest suite added.

Change-Id: I11076d90b80ec25ee604c29b6a6dc2337fd867ce
parent ff8351a3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6718,6 +6718,7 @@ package android.app.job {
    method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
    method public boolean isPeriodic();
    method public boolean isPersisted();
    method public boolean isRequireBatteryNotLow();
    method public boolean isRequireCharging();
    method public boolean isRequireDeviceIdle();
    method public void writeToParcel(android.os.Parcel, int);
@@ -6744,6 +6745,7 @@ package android.app.job {
    method public android.app.job.JobInfo.Builder setPeriodic(long, long);
    method public android.app.job.JobInfo.Builder setPersisted(boolean);
    method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
    method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
    method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
    method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
    method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
+2 −0
Original line number Diff line number Diff line
@@ -7110,6 +7110,7 @@ package android.app.job {
    method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
    method public boolean isPeriodic();
    method public boolean isPersisted();
    method public boolean isRequireBatteryNotLow();
    method public boolean isRequireCharging();
    method public boolean isRequireDeviceIdle();
    method public void writeToParcel(android.os.Parcel, int);
@@ -7136,6 +7137,7 @@ package android.app.job {
    method public android.app.job.JobInfo.Builder setPeriodic(long, long);
    method public android.app.job.JobInfo.Builder setPersisted(boolean);
    method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
    method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
    method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
    method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
    method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
+2 −0
Original line number Diff line number Diff line
@@ -6744,6 +6744,7 @@ package android.app.job {
    method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
    method public boolean isPeriodic();
    method public boolean isPersisted();
    method public boolean isRequireBatteryNotLow();
    method public boolean isRequireCharging();
    method public boolean isRequireDeviceIdle();
    method public void writeToParcel(android.os.Parcel, int);
@@ -6770,6 +6771,7 @@ package android.app.job {
    method public android.app.job.JobInfo.Builder setPeriodic(long, long);
    method public android.app.job.JobInfo.Builder setPersisted(boolean);
    method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
    method public android.app.job.JobInfo.Builder setRequiresBatteryNotLow(boolean);
    method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
    method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
    method public android.app.job.JobInfo.Builder setTransientExtras(android.os.Bundle);
+56 −17
Original line number Diff line number Diff line
@@ -174,12 +174,26 @@ public class JobInfo implements Parcelable {
     */
    public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0;

    /**
     * @hide
     */
    public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;

    /**
     * @hide
     */
    public static final int CONSTRAINT_FLAG_BATTERY_NOT_LOW = 1 << 1;

    /**
     * @hide
     */
    public static final int CONSTRAINT_FLAG_DEVICE_IDLE = 1 << 2;

    private final int jobId;
    private final PersistableBundle extras;
    private final Bundle transientExtras;
    private final ComponentName service;
    private final boolean requireCharging;
    private final boolean requireDeviceIdle;
    private final int constraintFlags;
    private final TriggerContentUri[] triggerContentUris;
    private final long triggerContentUpdateDelay;
    private final long triggerContentMaxDelay;
@@ -241,14 +255,28 @@ public class JobInfo implements Parcelable {
     * Whether this job needs the device to be plugged in.
     */
    public boolean isRequireCharging() {
        return requireCharging;
        return (constraintFlags & CONSTRAINT_FLAG_CHARGING) != 0;
    }

    /**
     * Whether this job needs the device's battery level to not be at below the critical threshold.
     */
    public boolean isRequireBatteryNotLow() {
        return (constraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0;
    }

    /**
     * Whether this job needs the device to be in an Idle maintenance window.
     */
    public boolean isRequireDeviceIdle() {
        return requireDeviceIdle;
        return (constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0;
    }

    /**
     * @hide
     */
    public int getConstraintFlags() {
        return constraintFlags;
    }

    /**
@@ -376,8 +404,7 @@ public class JobInfo implements Parcelable {
        extras = in.readPersistableBundle();
        transientExtras = in.readBundle();
        service = in.readParcelable(null);
        requireCharging = in.readInt() == 1;
        requireDeviceIdle = in.readInt() == 1;
        constraintFlags = in.readInt();
        triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
        triggerContentUpdateDelay = in.readLong();
        triggerContentMaxDelay = in.readLong();
@@ -401,8 +428,7 @@ public class JobInfo implements Parcelable {
        extras = b.mExtras.deepcopy();
        transientExtras = b.mTransientExtras.deepcopy();
        service = b.mJobService;
        requireCharging = b.mRequiresCharging;
        requireDeviceIdle = b.mRequiresDeviceIdle;
        constraintFlags = b.mConstraintFlags;
        triggerContentUris = b.mTriggerContentUris != null
                ? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
                : null;
@@ -434,8 +460,7 @@ public class JobInfo implements Parcelable {
        out.writePersistableBundle(extras);
        out.writeBundle(transientExtras);
        out.writeParcelable(service, flags);
        out.writeInt(requireCharging ? 1 : 0);
        out.writeInt(requireDeviceIdle ? 1 : 0);
        out.writeInt(constraintFlags);
        out.writeTypedArray(triggerContentUris, flags);
        out.writeLong(triggerContentUpdateDelay);
        out.writeLong(triggerContentMaxDelay);
@@ -563,8 +588,7 @@ public class JobInfo implements Parcelable {
        private int mPriority = PRIORITY_DEFAULT;
        private int mFlags;
        // Requirements.
        private boolean mRequiresCharging;
        private boolean mRequiresDeviceIdle;
        private int mConstraintFlags;
        private int mNetworkType;
        private ArrayList<TriggerContentUri> mTriggerContentUris;
        private long mTriggerContentUpdateDelay = -1;
@@ -651,7 +675,21 @@ public class JobInfo implements Parcelable {
         * @param requiresCharging Whether or not the device is plugged in.
         */
        public Builder setRequiresCharging(boolean requiresCharging) {
            mRequiresCharging = requiresCharging;
            mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_CHARGING)
                    | (requiresCharging ? CONSTRAINT_FLAG_CHARGING : 0);
            return this;
        }

        /**
         * Specify that to run this job, the device's battery level must not be low.
         * This defaults to false.  If true, the job will only run when the battery level
         * is not low, which is generally the point where the user is given a "low battery"
         * warning.
         * @param batteryNotLow Whether or not the device's battery level must not be low.
         */
        public Builder setRequiresBatteryNotLow(boolean batteryNotLow) {
            mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_BATTERY_NOT_LOW)
                    | (batteryNotLow ? CONSTRAINT_FLAG_BATTERY_NOT_LOW : 0);
            return this;
        }

@@ -666,7 +704,8 @@ public class JobInfo implements Parcelable {
         *                           window.
         */
        public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
            mRequiresDeviceIdle = requiresDeviceIdle;
            mConstraintFlags = (mConstraintFlags&~CONSTRAINT_FLAG_DEVICE_IDLE)
                    | (requiresDeviceIdle ? CONSTRAINT_FLAG_DEVICE_IDLE : 0);
            return this;
        }

@@ -816,8 +855,8 @@ public class JobInfo implements Parcelable {
         */
        public JobInfo build() {
            // Allow jobs with no constraints - What am I, a database?
            if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging &&
                    !mRequiresDeviceIdle && mNetworkType == NETWORK_TYPE_NONE &&
            if (!mHasEarlyConstraint && !mHasLateConstraint && mConstraintFlags == 0 &&
                    mNetworkType == NETWORK_TYPE_NONE &&
                    mTriggerContentUris == null) {
                throw new IllegalArgumentException("You're trying to build a job with no " +
                        "constraints, this is not allowed.");
@@ -843,7 +882,7 @@ public class JobInfo implements Parcelable {
                throw new IllegalArgumentException("Can't call setTransientExtras() on a " +
                        "persisted job");
            }
            if (mBackoffPolicySet && mRequiresDeviceIdle) {
            if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
                throw new IllegalArgumentException("An idle mode job will not respect any" +
                        " back-off policy, so calling setBackoffCriteria with" +
                        " setRequiresDeviceIdle is an error.");
+7 −0
Original line number Diff line number Diff line
@@ -118,6 +118,13 @@ public class BatteryManager {
     */
     public static final String EXTRA_CHARGE_COUNTER = "charge_counter";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Current int sequence number of the update.
     * {@hide}
     */
    public static final String EXTRA_SEQUENCE = "seq";

    // values for "status" field in the ACTION_BATTERY_CHANGED Intent
    public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN;
    public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING;
Loading