aboutsummaryrefslogtreecommitdiff
path: root/work/workmanager/src/main/java/androidx/work/Configuration.java
blob: 77f5ffa9b4428567bdcb1274d5b275cc804c80cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.work;

import static androidx.work.impl.Scheduler.MAX_SCHEDULER_LIMIT;

import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;

import androidx.work.impl.utils.IdGenerator;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Configuration for {@link WorkManager}.
 */
public final class Configuration {

    /**
     * The minimum number of system requests which can be enqueued by {@link WorkManager}
     * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
     */
    public static final int MIN_SCHEDULER_LIMIT = 20;

    private final Executor mExecutor;
    private final int mMinJobSchedulerId;
    private final int mMaxJobSchedulerId;
    private final int mMaxSchedulerLimit;

    private Configuration(@NonNull Configuration.Builder builder) {
        if (builder.mExecutor == null) {
            mExecutor = createDefaultExecutor();
        } else {
            mExecutor = builder.mExecutor;
        }
        mMinJobSchedulerId = builder.mMinJobSchedulerId;
        mMaxJobSchedulerId = builder.mMaxJobSchedulerId;
        mMaxSchedulerLimit = builder.mMaxSchedulerLimit;
    }

    /**
     * @return The {@link Executor} used by {@link WorkManager} to execute {@link Worker}s.
     */
    public @NonNull Executor getExecutor() {
        return mExecutor;
    }

    /**
     * @return The first valid id (inclusive) used by {@link WorkManager} when
     * creating new instances of {@link android.app.job.JobInfo}s.
     *
     * If the current {@code jobId} goes beyond the bounds of the defined range of
     * ({@link Configuration.Builder#getMinJobSchedulerID()},
     *  {@link Configuration.Builder#getMaxJobSchedulerID()}), it is reset to
     *  ({@link Configuration.Builder#getMinJobSchedulerID()}).
     */
    public int getMinJobSchedulerID() {
        return mMinJobSchedulerId;
    }

    /**
     * @return The last valid id (inclusive) used by {@link WorkManager} when
     * creating new instances of {@link android.app.job.JobInfo}s.
     *
     * If the current {@code jobId} goes beyond the bounds of the defined range of
     * ({@link Configuration.Builder#getMinJobSchedulerID()},
     *  {@link Configuration.Builder#getMaxJobSchedulerID()}), it is reset to
     *  ({@link Configuration.Builder#getMinJobSchedulerID()}).
     */
    public int getMaxJobSchedulerID() {
        return mMaxJobSchedulerId;
    }

    /**
     * @return The maximum number of system requests which can be enqueued by {@link WorkManager}
     * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
     *
     * @hide
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    public int getMaxSchedulerLimit() {
        // We double schedule jobs in SDK 23. So use half the number of max slots specified.
        if (Build.VERSION.SDK_INT == 23) {
            return mMaxSchedulerLimit / 2;
        } else {
            return mMaxSchedulerLimit;
        }
    }

    private Executor createDefaultExecutor() {
        return Executors.newFixedThreadPool(
                // This value is the same as the core pool size for AsyncTask#THREAD_POOL_EXECUTOR.
                Math.max(2, Math.min(Runtime.getRuntime().availableProcessors() - 1, 4)));
    }

    /**
     * A Builder for {@link Configuration}.
     */
    public static final class Builder {

        int mMinJobSchedulerId = IdGenerator.INITIAL_ID;
        int mMaxJobSchedulerId = Integer.MAX_VALUE;
        int mMaxSchedulerLimit = MIN_SCHEDULER_LIMIT;
        Executor mExecutor;

        /**
         * Specifies a custom {@link Executor} for WorkManager.
         *
         * @param executor An {@link Executor} for processing work
         * @return This {@link Builder} instance
         */
        public Builder setExecutor(@NonNull Executor executor) {
            mExecutor = executor;
            return this;
        }

        /**
         * Specifies the range of {@link android.app.job.JobInfo} IDs that can be used by
         * {@link WorkManager}. {@link WorkManager} needs a range of at least {@code 1000} IDs.
         *
         * @param minJobSchedulerId The first valid {@link android.app.job.JobInfo} ID inclusive.
         * @param maxJobSchedulerId The last valid {@link android.app.job.JobInfo} ID inclusive.
         * @return This {@link Builder} instance
         * @throws IllegalArgumentException when the size of the range is < 1000
         */
        public Builder setJobSchedulerJobIdRange(int minJobSchedulerId, int maxJobSchedulerId) {
            if ((maxJobSchedulerId - minJobSchedulerId) < 1000) {
                throw new IllegalArgumentException(
                        "WorkManager needs a range of at least 1000 job ids.");
            }

            mMinJobSchedulerId = minJobSchedulerId;
            mMaxJobSchedulerId = maxJobSchedulerId;
            return this;
        }

        /**
         * Specifies the maximum number of system requests made by {@link WorkManager}
         * when using {@link android.app.job.JobScheduler} or {@link android.app.AlarmManager}.
         * When the application exceeds this limit {@link WorkManager} maintains an internal queue
         * of {@link WorkRequest}s, and enqueues when slots become free.
         *
         * {@link WorkManager} requires a minimum of {@link Configuration#MIN_SCHEDULER_LIMIT}
         * slots. The total number of slots also cannot exceed {@code 100} which is
         * the {@link android.app.job.JobScheduler} limit.
         *
         * @param maxSchedulerLimit The total number of jobs which can be enqueued by
         *                                {@link WorkManager} when using
         *                                {@link android.app.job.JobScheduler}.
         * @return This {@link Builder} instance
         * @throws IllegalArgumentException when the number of jobs <
         *                                  {@link Configuration#MIN_SCHEDULER_LIMIT}
         */
        public Builder setMaxSchedulerLimit(int maxSchedulerLimit) {
            if (maxSchedulerLimit < MIN_SCHEDULER_LIMIT) {
                throw new IllegalArgumentException(
                        "WorkManager needs to be able to schedule at least 20 jobs in "
                                + "JobScheduler.");
            }
            mMaxSchedulerLimit = Math.min(maxSchedulerLimit, MAX_SCHEDULER_LIMIT);
            return this;
        }

        /**
         * Specifies a custom {@link Executor} for WorkManager.
         *
         * @param executor An {@link Executor} for processing work
         * @return This {@link Builder} instance
         * @deprecated Use the {@link Configuration.Builder#setExecutor(Executor)} method instead
         */
        @Deprecated
        public Builder withExecutor(@NonNull Executor executor) {
            mExecutor = executor;
            return this;
        }

        /**
         * Builds a {@link Configuration} object.
         *
         * @return A {@link Configuration} object with this {@link Builder}'s parameters.
         */
        public Configuration build() {
            return new Configuration(this);
        }
    }
}