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 Configuration(@onNull Configuration.Builder builder)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 */ getExecutor()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 */ getMinJobSchedulerID()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 */ getMaxJobSchedulerID()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) getMaxSchedulerLimit()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 createDefaultExecutor()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 */ setExecutor(@onNull Executor executor)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 */ setJobSchedulerJobIdRange(int minJobSchedulerId, int maxJobSchedulerId)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 */ setMaxSchedulerLimit(int maxSchedulerLimit)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 withExecutor(@onNull Executor executor)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 */ build()198 public Configuration build() { 199 return new Configuration(this); 200 } 201 } 202 } 203