Home | History | Annotate | Download | only in work
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.work;
     18 
     19 import static androidx.work.impl.Scheduler.MAX_SCHEDULER_LIMIT;
     20 
     21 import android.os.Build;
     22 import android.support.annotation.NonNull;
     23 import android.support.annotation.RestrictTo;
     24 
     25 import androidx.work.impl.utils.IdGenerator;
     26 
     27 import java.util.concurrent.Executor;
     28 import java.util.concurrent.Executors;
     29 
     30 /**
     31  * Configuration for {@link WorkManager}.
     32  */
     33 public final class Configuration {
     34 
     35     /**
     36      * The minimum number of system requests which can be enqueued by {@link WorkManager}
     37      * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
     38      */
     39     public static final int MIN_SCHEDULER_LIMIT = 20;
     40 
     41     private final Executor mExecutor;
     42     private final int mMinJobSchedulerId;
     43     private final int mMaxJobSchedulerId;
     44     private final int mMaxSchedulerLimit;
     45 
     46     private Configuration(@NonNull Configuration.Builder builder) {
     47         if (builder.mExecutor == null) {
     48             mExecutor = createDefaultExecutor();
     49         } else {
     50             mExecutor = builder.mExecutor;
     51         }
     52         mMinJobSchedulerId = builder.mMinJobSchedulerId;
     53         mMaxJobSchedulerId = builder.mMaxJobSchedulerId;
     54         mMaxSchedulerLimit = builder.mMaxSchedulerLimit;
     55     }
     56 
     57     /**
     58      * @return The {@link Executor} used by {@link WorkManager} to execute {@link Worker}s.
     59      */
     60     public @NonNull Executor getExecutor() {
     61         return mExecutor;
     62     }
     63 
     64     /**
     65      * @return The first valid id (inclusive) used by {@link WorkManager} when
     66      * creating new instances of {@link android.app.job.JobInfo}s.
     67      *
     68      * If the current {@code jobId} goes beyond the bounds of the defined range of
     69      * ({@link Configuration.Builder#getMinJobSchedulerID()},
     70      *  {@link Configuration.Builder#getMaxJobSchedulerID()}), it is reset to
     71      *  ({@link Configuration.Builder#getMinJobSchedulerID()}).
     72      */
     73     public int getMinJobSchedulerID() {
     74         return mMinJobSchedulerId;
     75     }
     76 
     77     /**
     78      * @return The last valid id (inclusive) used by {@link WorkManager} when
     79      * creating new instances of {@link android.app.job.JobInfo}s.
     80      *
     81      * If the current {@code jobId} goes beyond the bounds of the defined range of
     82      * ({@link Configuration.Builder#getMinJobSchedulerID()},
     83      *  {@link Configuration.Builder#getMaxJobSchedulerID()}), it is reset to
     84      *  ({@link Configuration.Builder#getMinJobSchedulerID()}).
     85      */
     86     public int getMaxJobSchedulerID() {
     87         return mMaxJobSchedulerId;
     88     }
     89 
     90     /**
     91      * @return The maximum number of system requests which can be enqueued by {@link WorkManager}
     92      * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
     93      *
     94      * @hide
     95      */
     96     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     97     public int getMaxSchedulerLimit() {
     98         // We double schedule jobs in SDK 23. So use half the number of max slots specified.
     99         if (Build.VERSION.SDK_INT == 23) {
    100             return mMaxSchedulerLimit / 2;
    101         } else {
    102             return mMaxSchedulerLimit;
    103         }
    104     }
    105 
    106     private Executor createDefaultExecutor() {
    107         return Executors.newFixedThreadPool(
    108                 // This value is the same as the core pool size for AsyncTask#THREAD_POOL_EXECUTOR.
    109                 Math.max(2, Math.min(Runtime.getRuntime().availableProcessors() - 1, 4)));
    110     }
    111 
    112     /**
    113      * A Builder for {@link Configuration}.
    114      */
    115     public static final class Builder {
    116 
    117         int mMinJobSchedulerId = IdGenerator.INITIAL_ID;
    118         int mMaxJobSchedulerId = Integer.MAX_VALUE;
    119         int mMaxSchedulerLimit = MIN_SCHEDULER_LIMIT;
    120         Executor mExecutor;
    121 
    122         /**
    123          * Specifies a custom {@link Executor} for WorkManager.
    124          *
    125          * @param executor An {@link Executor} for processing work
    126          * @return This {@link Builder} instance
    127          */
    128         public Builder setExecutor(@NonNull Executor executor) {
    129             mExecutor = executor;
    130             return this;
    131         }
    132 
    133         /**
    134          * Specifies the range of {@link android.app.job.JobInfo} IDs that can be used by
    135          * {@link WorkManager}. {@link WorkManager} needs a range of at least {@code 1000} IDs.
    136          *
    137          * @param minJobSchedulerId The first valid {@link android.app.job.JobInfo} ID inclusive.
    138          * @param maxJobSchedulerId The last valid {@link android.app.job.JobInfo} ID inclusive.
    139          * @return This {@link Builder} instance
    140          * @throws IllegalArgumentException when the size of the range is < 1000
    141          */
    142         public Builder setJobSchedulerJobIdRange(int minJobSchedulerId, int maxJobSchedulerId) {
    143             if ((maxJobSchedulerId - minJobSchedulerId) < 1000) {
    144                 throw new IllegalArgumentException(
    145                         "WorkManager needs a range of at least 1000 job ids.");
    146             }
    147 
    148             mMinJobSchedulerId = minJobSchedulerId;
    149             mMaxJobSchedulerId = maxJobSchedulerId;
    150             return this;
    151         }
    152 
    153         /**
    154          * Specifies the maximum number of system requests made by {@link WorkManager}
    155          * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
    156          * When the application exceeds this limit {@link WorkManager} maintains an internal queue
    157          * of {@link WorkRequest}s, and enqueues when slots become free.
    158          *
    159          * {@link WorkManager} requires a minimum of {@link Configuration#MIN_SCHEDULER_LIMIT}
    160          * slots. The total number of slots also cannot exceed {@code 100} which is
    161          * the {@link android.app.job.JobScheduler} limit.
    162          *
    163          * @param maxSchedulerLimit The total number of jobs which can be enqueued by
    164          *                                {@link WorkManager} when using
    165          *                                {@link android.app.job.JobScheduler}.
    166          * @return This {@link Builder} instance
    167          * @throws IllegalArgumentException when the number of jobs <
    168          *                                  {@link Configuration#MIN_SCHEDULER_LIMIT}
    169          */
    170         public Builder setMaxSchedulerLimit(int maxSchedulerLimit) {
    171             if (maxSchedulerLimit < MIN_SCHEDULER_LIMIT) {
    172                 throw new IllegalArgumentException(
    173                         "WorkManager needs to be able to schedule at least 20 jobs in "
    174                                 + "JobScheduler.");
    175             }
    176             mMaxSchedulerLimit = Math.min(maxSchedulerLimit, MAX_SCHEDULER_LIMIT);
    177             return this;
    178         }
    179 
    180         /**
    181          * Specifies a custom {@link Executor} for WorkManager.
    182          *
    183          * @param executor An {@link Executor} for processing work
    184          * @return This {@link Builder} instance
    185          * @deprecated Use the {@link Configuration.Builder#setExecutor(Executor)} method instead
    186          */
    187         @Deprecated
    188         public Builder withExecutor(@NonNull Executor executor) {
    189             mExecutor = executor;
    190             return this;
    191         }
    192 
    193         /**
    194          * Builds a {@link Configuration} object.
    195          *
    196          * @return A {@link Configuration} object with this {@link Builder}'s parameters.
    197          */
    198         public Configuration build() {
    199             return new Configuration(this);
    200         }
    201     }
    202 }
    203