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

Commit b79560f9 authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Allow for job namespacing."

parents 15c52c54 2ad1bf1a
Loading
Loading
Loading
Loading
+61 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.job.IJobScheduler;
import android.app.job.IUserVisibleJobObserver;
@@ -25,10 +26,13 @@ import android.app.job.JobScheduler;
import android.app.job.JobSnapshot;
import android.app.job.JobWorkItem;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
import android.util.ArrayMap;

import java.util.List;

import java.util.Map;
import java.util.Set;

/**
 * Concrete implementation of the JobScheduler interface
@@ -41,16 +45,42 @@ import java.util.List;
public class JobSchedulerImpl extends JobScheduler {
    IJobScheduler mBinder;
    private final Context mContext;
    private final String mNamespace;

    public JobSchedulerImpl(@NonNull Context context, IJobScheduler binder) {
        this(context, binder, null);
    }

    private JobSchedulerImpl(@NonNull Context context, IJobScheduler binder,
            @Nullable String namespace) {
        mContext = context;
        mBinder = binder;
        mNamespace = namespace;
    }

    private JobSchedulerImpl(JobSchedulerImpl jsi, @Nullable String namespace) {
        this(jsi.mContext, jsi.mBinder, namespace);
    }

    @NonNull
    @Override
    public JobScheduler forNamespace(@NonNull String namespace) {
        if (namespace == null) {
            throw new IllegalArgumentException("namespace cannot be null");
        }
        return new JobSchedulerImpl(this, namespace);
    }

    @Nullable
    @Override
    public String getNamespace() {
        return mNamespace;
    }

    @Override
    public int schedule(JobInfo job) {
        try {
            return mBinder.schedule(job);
            return mBinder.schedule(mNamespace, job);
        } catch (RemoteException e) {
            return JobScheduler.RESULT_FAILURE;
        }
@@ -59,7 +89,7 @@ public class JobSchedulerImpl extends JobScheduler {
    @Override
    public int enqueue(JobInfo job, JobWorkItem work) {
        try {
            return mBinder.enqueue(job, work);
            return mBinder.enqueue(mNamespace, job, work);
        } catch (RemoteException e) {
            return JobScheduler.RESULT_FAILURE;
        }
@@ -68,7 +98,7 @@ public class JobSchedulerImpl extends JobScheduler {
    @Override
    public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag) {
        try {
            return mBinder.scheduleAsPackage(job, packageName, userId, tag);
            return mBinder.scheduleAsPackage(mNamespace, job, packageName, userId, tag);
        } catch (RemoteException e) {
            return JobScheduler.RESULT_FAILURE;
        }
@@ -77,23 +107,44 @@ public class JobSchedulerImpl extends JobScheduler {
    @Override
    public void cancel(int jobId) {
        try {
            mBinder.cancel(jobId);
            mBinder.cancel(mNamespace, jobId);
        } catch (RemoteException e) {}

    }

    @Override
    public void cancelAll() {
        try {
            mBinder.cancelAll();
            mBinder.cancelAllInNamespace(mNamespace);
        } catch (RemoteException e) {}
    }

    @Override
    public void cancelInAllNamespaces() {
        try {
            mBinder.cancelAll();
        } catch (RemoteException e) {}
    }

    @Override
    public List<JobInfo> getAllPendingJobs() {
        try {
            return mBinder.getAllPendingJobs().getList();
            return mBinder.getAllPendingJobsInNamespace(mNamespace).getList();
        } catch (RemoteException e) {
            return null;
        }
    }

    @Override
    public Map<String, List<JobInfo>> getPendingJobsInAllNamespaces() {
        try {
            final Map<String, ParceledListSlice<JobInfo>> parceledList =
                    mBinder.getAllPendingJobs();
            final ArrayMap<String, List<JobInfo>> jobMap = new ArrayMap<>();
            final Set<String> keys = parceledList.keySet();
            for (String key : keys) {
                jobMap.put(key, parceledList.get(key).getList());
            }
            return jobMap;
        } catch (RemoteException e) {
            return null;
        }
@@ -102,7 +153,7 @@ public class JobSchedulerImpl extends JobScheduler {
    @Override
    public JobInfo getPendingJob(int jobId) {
        try {
            return mBinder.getPendingJob(jobId);
            return mBinder.getPendingJob(mNamespace, jobId);
        } catch (RemoteException e) {
            return null;
        }
@@ -111,7 +162,7 @@ public class JobSchedulerImpl extends JobScheduler {
    @Override
    public int getPendingJobReason(int jobId) {
        try {
            return mBinder.getPendingJobReason(jobId);
            return mBinder.getPendingJobReason(mNamespace, jobId);
        } catch (RemoteException e) {
            return PENDING_JOB_REASON_UNDEFINED;
        }
+11 −7
Original line number Diff line number Diff line
@@ -21,20 +21,24 @@ import android.app.job.JobInfo;
import android.app.job.JobSnapshot;
import android.app.job.JobWorkItem;
import android.content.pm.ParceledListSlice;
import java.util.Map;

 /**
  * IPC interface that supports the app-facing {@link #JobScheduler} api.
  * {@hide}
  */
interface IJobScheduler {
    int schedule(in JobInfo job);
    int enqueue(in JobInfo job, in JobWorkItem work);
    int scheduleAsPackage(in JobInfo job, String packageName, int userId, String tag);
    void cancel(int jobId);
    int schedule(String namespace, in JobInfo job);
    int enqueue(String namespace, in JobInfo job, in JobWorkItem work);
    int scheduleAsPackage(String namespace, in JobInfo job, String packageName, int userId, String tag);
    void cancel(String namespace, int jobId);
    void cancelAll();
    ParceledListSlice getAllPendingJobs();
    JobInfo getPendingJob(int jobId);
    int getPendingJobReason(int jobId);
    void cancelAllInNamespace(String namespace);
    // Returns Map<String, ParceledListSlice>, where the keys are the namespaces.
    Map<String, ParceledListSlice<JobInfo>> getAllPendingJobs();
    ParceledListSlice<JobInfo> getAllPendingJobsInNamespace(String namespace);
    JobInfo getPendingJob(String namespace, int jobId);
    int getPendingJobReason(String namespace, int jobId);
    boolean canRunLongJobs(String packageName);
    boolean hasRunLongJobsPermission(String packageName, int userId);
    List<JobInfo> getStartedJobs();
+3 −0
Original line number Diff line number Diff line
@@ -1251,6 +1251,9 @@ public class JobInfo implements Parcelable {
         * in them all being treated the same. The priorities each have slightly different
         * behaviors, as noted in their relevant javadoc.
         *
         * Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
         * the priority will only affect sorting order within the job's namespace.
         *
         * <b>NOTE:</b> Setting all of your jobs to high priority will not be
         * beneficial to your app and in fact may hurt its performance in the
         * long run.
+19 −1
Original line number Diff line number Diff line
@@ -277,6 +277,8 @@ public class JobParameters implements Parcelable {

    @UnsupportedAppUsage
    private final int jobId;
    @Nullable
    private final String mJobNamespace;
    private final PersistableBundle extras;
    private final Bundle transientExtras;
    private final ClipData clipData;
@@ -295,7 +297,7 @@ public class JobParameters implements Parcelable {
    private String debugStopReason; // Human readable stop reason for debugging.

    /** @hide */
    public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
    public JobParameters(IBinder callback, String namespace, int jobId, PersistableBundle extras,
            Bundle transientExtras, ClipData clipData, int clipGrantFlags,
            boolean overrideDeadlineExpired, boolean isExpedited,
            boolean isUserInitiated, Uri[] triggeredContentUris,
@@ -312,6 +314,7 @@ public class JobParameters implements Parcelable {
        this.mTriggeredContentUris = triggeredContentUris;
        this.mTriggeredContentAuthorities = triggeredContentAuthorities;
        this.network = network;
        this.mJobNamespace = namespace;
    }

    /**
@@ -321,6 +324,19 @@ public class JobParameters implements Parcelable {
        return jobId;
    }

    /**
     * Get the namespace this job was placed in.
     *
     * @see JobScheduler#forNamespace(String)
     * @return The namespace this job was scheduled in. Will be {@code null} if there was no
     * explicit namespace set and this job is therefore in the default namespace.
     * @hide
     */
    @Nullable
    public String getJobNamespace() {
        return mJobNamespace;
    }

    /**
     * @return The reason {@link JobService#onStopJob(JobParameters)} was called on this job. Will
     * be {@link #STOP_REASON_UNDEFINED} if {@link JobService#onStopJob(JobParameters)} has not
@@ -540,6 +556,7 @@ public class JobParameters implements Parcelable {

    private JobParameters(Parcel in) {
        jobId = in.readInt();
        mJobNamespace = in.readString();
        extras = in.readPersistableBundle();
        transientExtras = in.readBundle();
        if (in.readInt() != 0) {
@@ -581,6 +598,7 @@ public class JobParameters implements Parcelable {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(jobId);
        dest.writeString(mJobNamespace);
        dest.writePersistableBundle(extras);
        dest.writeBundle(transientExtras);
        if (clipData != null) {
+50 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.os.PersistableBundle;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Map;

/**
 * This is an API for scheduling various types of jobs against the framework that will be executed
@@ -263,6 +264,31 @@ public abstract class JobScheduler {
    public @interface PendingJobReason {
    }

    /**
     * Get a JobScheduler instance that is dedicated to a specific namespace. Any API calls using
     * this instance will interact with jobs in that namespace, unless the API documentation says
     * otherwise. Attempting to update a job scheduled in another namespace will not be possible
     * but will instead create or update the job inside the current namespace. A JobScheduler
     * instance dedicated to a namespace must be used to schedule or update jobs in that namespace.
     * @see #getNamespace()
     * @hide
     */
    @NonNull
    public JobScheduler forNamespace(@NonNull String namespace) {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    /**
     * Get the namespace this JobScheduler instance is operating in. A {@code null} value means
     * that the app has not specified a namespace for this instance, and it is therefore using the
     * default namespace.
     * @hide
     */
    @Nullable
    public String getNamespace() {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    /**
     * Schedule a job to be executed.  Will replace any currently scheduled job with the same
     * ID with the new information in the {@link JobInfo}.  If a job with the given ID is currently
@@ -363,6 +389,15 @@ public abstract class JobScheduler {
     */
    public abstract void cancelAll();

    /**
     * Cancel <em>all</em> jobs that have been scheduled by the calling application, regardless of
     * namespace.
     * @hide
     */
    public void cancelInAllNamespaces() {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    /**
     * Retrieve all jobs that have been scheduled by the calling application.
     *
@@ -371,6 +406,21 @@ public abstract class JobScheduler {
     */
    public abstract @NonNull List<JobInfo> getAllPendingJobs();

    /**
     * Retrieve all jobs that have been scheduled by the calling application within the current
     * namespace.
     *
     * @return a list of all of the app's scheduled jobs scheduled with the current namespace.
     * If a namespace hasn't been explicitly set with {@link #forNamespace(String)},
     * then this will return jobs in the default namespace.
     * This includes jobs that are currently started as well as those that are still waiting to run.
     * @hide
     */
    @NonNull
    public Map<String, List<JobInfo>> getPendingJobsInAllNamespaces() {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    /**
     * Look up the description of a scheduled job.
     *
Loading