// Path: library/src/main/java/com/doist/jobschedulercompat/JobParameters.java
// public class JobParameters {
//     private final int jobId;
//     private final PersistableBundle extras;
//     private final Bundle transientExtras;
//     private final Network network;
//     private final Uri[] triggeredContentUris;
//     private final String[] triggeredContentAuthorities;
//     private final boolean overrideDeadlineExpired;
// 
//     @RestrictTo(RestrictTo.Scope.LIBRARY)
//     public JobParameters(int jobId, PersistableBundle extras, Bundle transientExtras, Network network,
//                          Uri[] triggeredContentUris, String[] triggeredContentAuthorities,
//                          boolean overrideDeadlineExpired) {
//         this.jobId = jobId;
//         this.extras = extras;
//         this.transientExtras = transientExtras;
//         this.network = network;
//         this.triggeredContentUris = triggeredContentUris;
//         this.triggeredContentAuthorities = triggeredContentAuthorities;
//         this.overrideDeadlineExpired = overrideDeadlineExpired;
//     }
// 
//     /** @see android.app.job.JobParameters#getJobId() */
//     public int getJobId() {
//         return jobId;
//     }
// 
//     /** @see android.app.job.JobParameters#getExtras() */
//     @NonNull
//     public PersistableBundle getExtras() {
//         return extras;
//     }
// 
//     /** @see android.app.job.JobParameters#getTransientExtras() */
//     @NonNull
//     public Bundle getTransientExtras() {
//         return transientExtras;
//     }
// 
//     /** @see android.app.job.JobParameters#getNetwork() */
//     @RequiresApi(Build.VERSION_CODES.P)
//     @Nullable
//     public Network getNetwork() {
//         return network;
//     }
// 
//     /** @see android.app.job.JobParameters#getTriggeredContentUris() */
//     @Nullable
//     public Uri[] getTriggeredContentUris() {
//         return triggeredContentUris;
//     }
// 
//     /** @see android.app.job.JobParameters#getTriggeredContentAuthorities() */
//     @Nullable
//     public String[] getTriggeredContentAuthorities() {
//         return triggeredContentAuthorities;
//     }
// 
//     /** @see android.app.job.JobParameters#isOverrideDeadlineExpired() */
//     public boolean isOverrideDeadlineExpired() {
//         return overrideDeadlineExpired;
//     }
// }
// 
// Path: library/src/main/java/com/doist/jobschedulercompat/JobService.java
// public abstract class JobService extends Service {
//     private Binder binder;
// 
//     @NonNull
//     @Override
//     public final IBinder onBind(Intent intent) {
//         if (binder == null) {
//             binder = new Binder(this);
//         }
//         return binder;
//     }
// 
//     /** @see android.app.job.JobService#onStartJob(android.app.job.JobParameters) */
//     public abstract boolean onStartJob(JobParameters params);
// 
//     /** @see android.app.job.JobService#onStopJob(android.app.job.JobParameters) */
//     public abstract boolean onStopJob(JobParameters params);
// 
//     /** @see android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean) */
//     public final void jobFinished(JobParameters params, boolean needsReschedule) {
//         if (binder != null) {
//             binder.notifyJobFinished(params, needsReschedule);
//         }
//     }
// 
//     /**
//      * Proxies callbacks between the scheduler job service that is handling the work and the user's {@link JobService}.
//      *
//      * All scheduler job services bind to this service to proxy their lifecycle. This allows maintaining parity with
//      * JobScheduler's API, while hiding implementation details away from the user.
//      *
//      * Methods are synchronized to prevent race conditions when updating {@link #callbacks}.
//      * There are no guarantees on which thread calls {@link #notifyJobFinished(JobParameters, boolean)}.
//      */
//     @RestrictTo(RestrictTo.Scope.LIBRARY)
//     public static class Binder extends android.os.Binder {
//         private final WeakReference<JobService> serviceRef;
//         private final SparseArray<Callback> callbacks;
// 
//         Binder(JobService service) {
//             super();
//             this.serviceRef = new WeakReference<>(service);
//             this.callbacks = new SparseArray<>(1);
//         }
// 
//         public synchronized boolean startJob(JobParameters params, Callback callback) {
//             JobService service = serviceRef.get();
//             if (service != null) {
//                 callbacks.put(params.getJobId(), callback);
//                 boolean willContinueRunning = service.onStartJob(params);
//                 if (!willContinueRunning) {
//                     callbacks.remove(params.getJobId());
//                 }
//                 return willContinueRunning;
//             } else {
//                 return false;
//             }
//         }
// 
//         public synchronized boolean stopJob(JobParameters params) {
//             JobService service = serviceRef.get();
//             if (service != null) {
//                 callbacks.remove(params.getJobId());
//                 return service.onStopJob(params);
//             } else {
//                 return false;
//             }
//         }
// 
//         synchronized void notifyJobFinished(JobParameters params, boolean needsReschedule) {
//             Callback callback = callbacks.get(params.getJobId());
//             if (callback != null) {
//                 callbacks.remove(params.getJobId());
//                 callback.jobFinished(params, needsReschedule);
//             }
//         }
// 
//         public interface Callback {
//             void jobFinished(JobParameters params, boolean needsReschedule);
//         }
//     }
// }


import com.doist.jobschedulercompat.JobParameters;
import com.doist.jobschedulercompat.JobService;
import android.util.SparseArray;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
package com.doist.jobschedulercompat.util;




public class NoopAsyncJobService extends JobService {
    public static final String EXTRA_DELAY = "delay";

    private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(0);
    private static final SparseArray<ScheduledFuture> futures = new SparseArray<>();

    @Override
// Path: library/src/main/java/com/doist/jobschedulercompat/JobParameters.java
// public class JobParameters {
//     private final int jobId;
//     private final PersistableBundle extras;
//     private final Bundle transientExtras;
//     private final Network network;
//     private final Uri[] triggeredContentUris;
//     private final String[] triggeredContentAuthorities;
//     private final boolean overrideDeadlineExpired;
// 
//     @RestrictTo(RestrictTo.Scope.LIBRARY)
//     public JobParameters(int jobId, PersistableBundle extras, Bundle transientExtras, Network network,
//                          Uri[] triggeredContentUris, String[] triggeredContentAuthorities,
//                          boolean overrideDeadlineExpired) {
//         this.jobId = jobId;
//         this.extras = extras;
//         this.transientExtras = transientExtras;
//         this.network = network;
//         this.triggeredContentUris = triggeredContentUris;
//         this.triggeredContentAuthorities = triggeredContentAuthorities;
//         this.overrideDeadlineExpired = overrideDeadlineExpired;
//     }
// 
//     /** @see android.app.job.JobParameters#getJobId() */
//     public int getJobId() {
//         return jobId;
//     }
// 
//     /** @see android.app.job.JobParameters#getExtras() */
//     @NonNull
//     public PersistableBundle getExtras() {
//         return extras;
//     }
// 
//     /** @see android.app.job.JobParameters#getTransientExtras() */
//     @NonNull
//     public Bundle getTransientExtras() {
//         return transientExtras;
//     }
// 
//     /** @see android.app.job.JobParameters#getNetwork() */
//     @RequiresApi(Build.VERSION_CODES.P)
//     @Nullable
//     public Network getNetwork() {
//         return network;
//     }
// 
//     /** @see android.app.job.JobParameters#getTriggeredContentUris() */
//     @Nullable
//     public Uri[] getTriggeredContentUris() {
//         return triggeredContentUris;
//     }
// 
//     /** @see android.app.job.JobParameters#getTriggeredContentAuthorities() */
//     @Nullable
//     public String[] getTriggeredContentAuthorities() {
//         return triggeredContentAuthorities;
//     }
// 
//     /** @see android.app.job.JobParameters#isOverrideDeadlineExpired() */
//     public boolean isOverrideDeadlineExpired() {
//         return overrideDeadlineExpired;
//     }
// }
// 
// Path: library/src/main/java/com/doist/jobschedulercompat/JobService.java
// public abstract class JobService extends Service {
//     private Binder binder;
// 
//     @NonNull
//     @Override
//     public final IBinder onBind(Intent intent) {
//         if (binder == null) {
//             binder = new Binder(this);
//         }
//         return binder;
//     }
// 
//     /** @see android.app.job.JobService#onStartJob(android.app.job.JobParameters) */
//     public abstract boolean onStartJob(JobParameters params);
// 
//     /** @see android.app.job.JobService#onStopJob(android.app.job.JobParameters) */
//     public abstract boolean onStopJob(JobParameters params);
// 
//     /** @see android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean) */
//     public final void jobFinished(JobParameters params, boolean needsReschedule) {
//         if (binder != null) {
//             binder.notifyJobFinished(params, needsReschedule);
//         }
//     }
// 
//     /**
//      * Proxies callbacks between the scheduler job service that is handling the work and the user's {@link JobService}.
//      *
//      * All scheduler job services bind to this service to proxy their lifecycle. This allows maintaining parity with
//      * JobScheduler's API, while hiding implementation details away from the user.
//      *
//      * Methods are synchronized to prevent race conditions when updating {@link #callbacks}.
//      * There are no guarantees on which thread calls {@link #notifyJobFinished(JobParameters, boolean)}.
//      */
//     @RestrictTo(RestrictTo.Scope.LIBRARY)
//     public static class Binder extends android.os.Binder {
//         private final WeakReference<JobService> serviceRef;
//         private final SparseArray<Callback> callbacks;
// 
//         Binder(JobService service) {
//             super();
//             this.serviceRef = new WeakReference<>(service);
//             this.callbacks = new SparseArray<>(1);
//         }
// 
//         public synchronized boolean startJob(JobParameters params, Callback callback) {
//             JobService service = serviceRef.get();
//             if (service != null) {
//                 callbacks.put(params.getJobId(), callback);
//                 boolean willContinueRunning = service.onStartJob(params);
//                 if (!willContinueRunning) {
//                     callbacks.remove(params.getJobId());
//                 }
//                 return willContinueRunning;
//             } else {
//                 return false;
//             }
//         }
// 
//         public synchronized boolean stopJob(JobParameters params) {
//             JobService service = serviceRef.get();
//             if (service != null) {
//                 callbacks.remove(params.getJobId());
//                 return service.onStopJob(params);
//             } else {
//                 return false;
//             }
//         }
// 
//         synchronized void notifyJobFinished(JobParameters params, boolean needsReschedule) {
//             Callback callback = callbacks.get(params.getJobId());
//             if (callback != null) {
//                 callbacks.remove(params.getJobId());
//                 callback.jobFinished(params, needsReschedule);
//             }
//         }
// 
//         public interface Callback {
//             void jobFinished(JobParameters params, boolean needsReschedule);
//         }
//     }
// }


// Path: library/src/test/java/com/doist/jobschedulercompat/util/NoopAsyncJobService.java
import com.doist.jobschedulercompat.JobParameters;
import com.doist.jobschedulercompat.JobService;
import android.util.SparseArray;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

package com.doist.jobschedulercompat.util;




public class NoopAsyncJobService extends JobService {
    public static final String EXTRA_DELAY = "delay";

    private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(0);
    private static final SparseArray<ScheduledFuture> futures = new SparseArray<>();

    @Override
    public boolean onStartJob(final JobParameters params) {