blob: e42713f0e1905a31b3e75f3563dad6046124d9b9 [file] [log] [blame]
Sumir Kataria904ba122017-09-25 13:05:49 -07001/*
2 * Copyright (C) 2017 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
Sumir Kataria564e4302018-02-14 11:22:30 -080017package androidx.work.impl.model;
Sumir Kataria904ba122017-09-25 13:05:49 -070018
Sumir Kataria8b3284f2018-04-13 09:50:18 -070019import static androidx.work.PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS;
20import static androidx.work.PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS;
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -070021import static androidx.work.WorkInfo.State.ENQUEUED;
Rahul Ravikumar7031a0f2018-04-19 14:24:30 -070022import static androidx.work.WorkRequest.MAX_BACKOFF_MILLIS;
23import static androidx.work.WorkRequest.MIN_BACKOFF_MILLIS;
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -080024
Sumir Kataria4401f792018-03-20 12:52:38 -070025import android.arch.core.util.Function;
Sumir Kataria904ba122017-09-25 13:05:49 -070026import android.arch.persistence.room.ColumnInfo;
27import android.arch.persistence.room.Embedded;
28import android.arch.persistence.room.Entity;
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -070029import android.arch.persistence.room.Index;
Sumir Kataria904ba122017-09-25 13:05:49 -070030import android.arch.persistence.room.PrimaryKey;
Sumir Katariacc5ae8c2018-03-12 12:57:46 -070031import android.arch.persistence.room.Relation;
Sumir Kataria904ba122017-09-25 13:05:49 -070032import android.support.annotation.NonNull;
Sumir Katariab5728f42018-03-19 12:58:41 -070033import android.support.annotation.RestrictTo;
Sumir Katariacc5ae8c2018-03-12 12:57:46 -070034
Sumir Kataria564e4302018-02-14 11:22:30 -080035import androidx.work.BackoffPolicy;
Sumir Kataria564e4302018-02-14 11:22:30 -080036import androidx.work.Constraints;
Sumir Kataria64e6bd82018-03-28 17:14:22 -070037import androidx.work.Data;
Sumir Katariafd60d222018-06-22 16:23:41 -070038import androidx.work.Logger;
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -070039import androidx.work.WorkInfo;
Rahul Ravikumar7031a0f2018-04-19 14:24:30 -070040import androidx.work.WorkRequest;
Sumir Kataria564e4302018-02-14 11:22:30 -080041
Sumir Kataria4401f792018-03-20 12:52:38 -070042import java.util.ArrayList;
Sumir Katariab5728f42018-03-19 12:58:41 -070043import java.util.List;
Sumir Katariafa284c92018-04-23 14:25:53 -070044import java.util.UUID;
Sumir Katariab5728f42018-03-19 12:58:41 -070045
Sumir Kataria904ba122017-09-25 13:05:49 -070046/**
47 * Stores information about a logical unit of work.
Sumir Katariab5728f42018-03-19 12:58:41 -070048 *
49 * @hide
Sumir Kataria904ba122017-09-25 13:05:49 -070050 */
Sumir Katariab5728f42018-03-19 12:58:41 -070051@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -070052@Entity(
53 indices = {@Index(value = {"schedule_requested_at"})}
54)
Sumir Kataria904ba122017-09-25 13:05:49 -070055public class WorkSpec {
Xyan Bhatnagar367c6492017-10-06 11:20:02 -070056 private static final String TAG = "WorkSpec";
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -070057 public static final long SCHEDULE_NOT_REQUESTED_YET = -1;
Sumir Kataria904ba122017-09-25 13:05:49 -070058
59 @ColumnInfo(name = "id")
60 @PrimaryKey
61 @NonNull
Sumir Katariab5728f42018-03-19 12:58:41 -070062 public String id;
Sumir Kataria904ba122017-09-25 13:05:49 -070063
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -080064 @ColumnInfo(name = "state")
Sumir Kataria86894df2018-03-06 15:11:16 -080065 @NonNull
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -070066 public WorkInfo.State state = ENQUEUED;
Sumir Kataria904ba122017-09-25 13:05:49 -070067
Jan Clarinee302e12017-10-09 11:16:19 -070068 @ColumnInfo(name = "worker_class_name")
Sumir Kataria86894df2018-03-06 15:11:16 -080069 @NonNull
Sumir Katariab5728f42018-03-19 12:58:41 -070070 public String workerClassName;
Jan Clarinee302e12017-10-09 11:16:19 -070071
Sumir Katariaa48d7ac2017-11-28 16:24:15 -080072 @ColumnInfo(name = "input_merger_class_name")
Sumir Katariab5728f42018-03-19 12:58:41 -070073 public String inputMergerClassName;
Sumir Katariaa48d7ac2017-11-28 16:24:15 -080074
Sumir Kataria64e6bd82018-03-28 17:14:22 -070075 @ColumnInfo(name = "input")
Sumir Kataria9244d372017-11-30 13:39:07 -080076 @NonNull
Sumir Kataria64e6bd82018-03-28 17:14:22 -070077 public Data input = Data.EMPTY;
Sumir Kataria9244d372017-11-30 13:39:07 -080078
79 @ColumnInfo(name = "output")
80 @NonNull
Sumir Kataria64e6bd82018-03-28 17:14:22 -070081 public Data output = Data.EMPTY;
Sumir Kataria9244d372017-11-30 13:39:07 -080082
Xyan Bhatnagara1af78b2017-10-04 17:36:36 -070083 @ColumnInfo(name = "initial_delay")
Sumir Katariab5728f42018-03-19 12:58:41 -070084 public long initialDelay;
Xyan Bhatnagara1af78b2017-10-04 17:36:36 -070085
Jan Clarinee302e12017-10-09 11:16:19 -070086 @ColumnInfo(name = "interval_duration")
Sumir Katariab5728f42018-03-19 12:58:41 -070087 public long intervalDuration;
Jan Clarinee302e12017-10-09 11:16:19 -070088
89 @ColumnInfo(name = "flex_duration")
Sumir Katariab5728f42018-03-19 12:58:41 -070090 public long flexDuration;
Sumir Kataria904ba122017-09-25 13:05:49 -070091
92 @Embedded
Sumir Kataria86894df2018-03-06 15:11:16 -080093 @NonNull
Sumir Katariab5728f42018-03-19 12:58:41 -070094 public Constraints constraints = Constraints.NONE;
Sumir Kataria904ba122017-09-25 13:05:49 -070095
Xyan Bhatnagar367c6492017-10-06 11:20:02 -070096 @ColumnInfo(name = "run_attempt_count")
Sumir Katariab5728f42018-03-19 12:58:41 -070097 public int runAttemptCount;
Xyan Bhatnagar367c6492017-10-06 11:20:02 -070098
Sumir Kataria904ba122017-09-25 13:05:49 -070099 @ColumnInfo(name = "backoff_policy")
Sumir Kataria86894df2018-03-06 15:11:16 -0800100 @NonNull
Sumir Katariab5728f42018-03-19 12:58:41 -0700101 public BackoffPolicy backoffPolicy = BackoffPolicy.EXPONENTIAL;
Sumir Kataria904ba122017-09-25 13:05:49 -0700102
103 @ColumnInfo(name = "backoff_delay_duration")
Rahul Ravikumar7031a0f2018-04-19 14:24:30 -0700104 public long backoffDelayDuration = WorkRequest.DEFAULT_BACKOFF_DELAY_MILLIS;
Sumir Kataria904ba122017-09-25 13:05:49 -0700105
Sumir Katariab5728f42018-03-19 12:58:41 -0700106 /**
107 * For one-off work, this is the time that the work was unblocked by prerequisites.
108 * For periodic work, this is the time that the period started.
109 */
Jan Clarin0deb5e22017-12-06 11:26:29 -0800110 @ColumnInfo(name = "period_start_time")
Sumir Katariab5728f42018-03-19 12:58:41 -0700111 public long periodStartTime;
Jan Clarin0deb5e22017-12-06 11:26:29 -0800112
Sumir Kataria3d5949e2018-03-06 13:32:20 -0800113 @ColumnInfo(name = "minimum_retention_duration")
Sumir Katariab5728f42018-03-19 12:58:41 -0700114 public long minimumRetentionDuration;
Sumir Kataria3d5949e2018-03-06 13:32:20 -0800115
Rahul Ravikumarfe793bc2018-07-09 12:43:26 -0700116 /**
117 * This field tells us if this {@link WorkSpec} instance, is actually currently scheduled and
118 * being counted against the {@code SCHEDULER_LIMIT}. This bit is reset for PeriodicWorkRequests
119 * in API < 23, because AlarmManager does not know of PeriodicWorkRequests. So for the next
120 * request to be rescheduled this field has to be reset to {@code SCHEDULE_NOT_REQUESTED_AT}.
121 * For the JobScheduler implementation, we don't reset this field because JobScheduler natively
122 * supports PeriodicWorkRequests.
123 */
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -0700124 @ColumnInfo(name = "schedule_requested_at")
125 public long scheduleRequestedAt = SCHEDULE_NOT_REQUESTED_YET;
126
Sumir Katariab5728f42018-03-19 12:58:41 -0700127 public WorkSpec(@NonNull String id, @NonNull String workerClassName) {
128 this.id = id;
129 this.workerClassName = workerClassName;
Sumir Kataria904ba122017-09-25 13:05:49 -0700130 }
131
Sumir Katariaa31df0312018-07-27 14:28:01 -0700132 public WorkSpec(@NonNull WorkSpec other) {
133 id = other.id;
134 workerClassName = other.workerClassName;
135 state = other.state;
136 inputMergerClassName = other.inputMergerClassName;
137 input = new Data(other.input);
138 output = new Data(other.output);
139 initialDelay = other.initialDelay;
140 intervalDuration = other.intervalDuration;
141 flexDuration = other.flexDuration;
142 constraints = new Constraints(other.constraints);
143 runAttemptCount = other.runAttemptCount;
144 backoffPolicy = other.backoffPolicy;
145 backoffDelayDuration = other.backoffDelayDuration;
146 periodStartTime = other.periodStartTime;
147 minimumRetentionDuration = other.minimumRetentionDuration;
148 scheduleRequestedAt = other.scheduleRequestedAt;
149 }
150
Sumir Kataria564e4302018-02-14 11:22:30 -0800151 /**
152 * @param backoffDelayDuration The backoff delay duration in milliseconds
153 */
Sumir Kataria904ba122017-09-25 13:05:49 -0700154 public void setBackoffDelayDuration(long backoffDelayDuration) {
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800155 if (backoffDelayDuration > MAX_BACKOFF_MILLIS) {
Sumir Katariabd134a02018-11-29 16:02:17 -0800156 Logger.get().warning(TAG, "Backoff delay duration exceeds maximum value");
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800157 backoffDelayDuration = MAX_BACKOFF_MILLIS;
158 }
159 if (backoffDelayDuration < MIN_BACKOFF_MILLIS) {
Sumir Katariabd134a02018-11-29 16:02:17 -0800160 Logger.get().warning(TAG, "Backoff delay duration less than minimum value");
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800161 backoffDelayDuration = MIN_BACKOFF_MILLIS;
162 }
Sumir Katariab5728f42018-03-19 12:58:41 -0700163 this.backoffDelayDuration = backoffDelayDuration;
Sumir Kataria904ba122017-09-25 13:05:49 -0700164 }
Xyan Bhatnagara1af78b2017-10-04 17:36:36 -0700165
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700166
Jan Clarinee302e12017-10-09 11:16:19 -0700167 public boolean isPeriodic() {
Sumir Katariab5728f42018-03-19 12:58:41 -0700168 return intervalDuration != 0L;
Jan Clarinee302e12017-10-09 11:16:19 -0700169 }
170
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800171 public boolean isBackedOff() {
Sumir Katariab5728f42018-03-19 12:58:41 -0700172 return state == ENQUEUED && runAttemptCount > 0;
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800173 }
174
Sumir Kataria6d55d8c2017-12-07 13:37:42 -0800175 /**
176 * Sets the periodic interval for this unit of work.
177 *
178 * @param intervalDuration The interval in milliseconds
179 */
Jan Clarinee302e12017-10-09 11:16:19 -0700180 public void setPeriodic(long intervalDuration) {
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800181 if (intervalDuration < MIN_PERIODIC_INTERVAL_MILLIS) {
Sumir Katariabd134a02018-11-29 16:02:17 -0800182 Logger.get().warning(TAG, String.format(
Rahul Ravikumar697d6a42018-04-16 15:44:09 -0700183 "Interval duration lesser than minimum allowed value; Changed to %s",
184 MIN_PERIODIC_INTERVAL_MILLIS));
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800185 intervalDuration = MIN_PERIODIC_INTERVAL_MILLIS;
186 }
Jan Clarinee302e12017-10-09 11:16:19 -0700187 setPeriodic(intervalDuration, intervalDuration);
188 }
189
Sumir Kataria6d55d8c2017-12-07 13:37:42 -0800190 /**
191 * Sets the periodic interval for this unit of work.
192 *
193 * @param intervalDuration The interval in milliseconds
194 * @param flexDuration The flex duration in milliseconds
195 */
Jan Clarinee302e12017-10-09 11:16:19 -0700196 public void setPeriodic(long intervalDuration, long flexDuration) {
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800197 if (intervalDuration < MIN_PERIODIC_INTERVAL_MILLIS) {
Sumir Katariabd134a02018-11-29 16:02:17 -0800198 Logger.get().warning(TAG, String.format(
Rahul Ravikumar697d6a42018-04-16 15:44:09 -0700199 "Interval duration lesser than minimum allowed value; Changed to %s",
200 MIN_PERIODIC_INTERVAL_MILLIS));
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800201 intervalDuration = MIN_PERIODIC_INTERVAL_MILLIS;
202 }
203 if (flexDuration < MIN_PERIODIC_FLEX_MILLIS) {
Sumir Katariabd134a02018-11-29 16:02:17 -0800204 Logger.get().warning(TAG,
Rahul Ravikumar697d6a42018-04-16 15:44:09 -0700205 String.format("Flex duration lesser than minimum allowed value; Changed to %s",
206 MIN_PERIODIC_FLEX_MILLIS));
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800207 flexDuration = MIN_PERIODIC_FLEX_MILLIS;
208 }
209 if (flexDuration > intervalDuration) {
Sumir Katariabd134a02018-11-29 16:02:17 -0800210 Logger.get().warning(TAG,
Sumir Katariafd60d222018-06-22 16:23:41 -0700211 String.format("Flex duration greater than interval duration; Changed to %s",
Rahul Ravikumar697d6a42018-04-16 15:44:09 -0700212 intervalDuration));
Sumir Kataria1cd0e4e2017-12-12 10:53:46 -0800213 flexDuration = intervalDuration;
214 }
Sumir Katariab5728f42018-03-19 12:58:41 -0700215 this.intervalDuration = intervalDuration;
216 this.flexDuration = flexDuration;
Sumir Kataria3d5949e2018-03-06 13:32:20 -0800217 }
218
Jan Clarin0deb5e22017-12-06 11:26:29 -0800219 /**
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800220 * Calculates the UTC time at which this {@link WorkSpec} should be allowed to run.
221 * This method accounts for work that is backed off or periodic.
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700222 *
Sumir Katariab6430f22018-02-05 13:45:22 -0800223 * If Backoff Policy is set to {@link BackoffPolicy#EXPONENTIAL}, then delay
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700224 * increases at an exponential rate with respect to the run attempt count and is capped at
Rahul Ravikumar7031a0f2018-04-19 14:24:30 -0700225 * {@link WorkRequest#MAX_BACKOFF_MILLIS}.
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700226 *
Sumir Katariab6430f22018-02-05 13:45:22 -0800227 * If Backoff Policy is set to {@link BackoffPolicy#LINEAR}, then delay
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700228 * increases at an linear rate with respect to the run attempt count and is capped at
Rahul Ravikumar7031a0f2018-04-19 14:24:30 -0700229 * {@link WorkRequest#MAX_BACKOFF_MILLIS}.
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700230 *
231 * Based on {@see https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/job/JobSchedulerService.java#1125}
232 *
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800233 * Note that this runtime is for WorkManager internal use and may not match what the OS
234 * considers to be the next runtime.
Sumir Kataria58e4d6f2017-11-14 14:31:15 -0800235 *
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800236 * For jobs with constraints, this represents the earliest time at which constraints
237 * should be monitored for this work.
238 *
239 * For jobs without constraints, this represents the earliest time at which this work is
240 * allowed to run.
241 *
242 * @return UTC time at which this {@link WorkSpec} should be allowed to run.
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700243 */
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800244 public long calculateNextRunTime() {
245 if (isBackedOff()) {
Sumir Katariab5728f42018-03-19 12:58:41 -0700246 boolean isLinearBackoff = (backoffPolicy == BackoffPolicy.LINEAR);
247 long delay = isLinearBackoff ? (backoffDelayDuration * runAttemptCount)
248 : (long) Math.scalb(backoffDelayDuration, runAttemptCount - 1);
Rahul Ravikumar7031a0f2018-04-19 14:24:30 -0700249 return periodStartTime + Math.min(WorkRequest.MAX_BACKOFF_MILLIS, delay);
Xyan Bhatnagar1c78bb22017-12-08 15:48:19 -0800250 } else if (isPeriodic()) {
Sumir Katariab5728f42018-03-19 12:58:41 -0700251 return periodStartTime + intervalDuration - flexDuration;
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700252 } else {
Sumir Katariab5728f42018-03-19 12:58:41 -0700253 return periodStartTime + initialDelay;
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700254 }
Xyan Bhatnagar367c6492017-10-06 11:20:02 -0700255 }
Jan Clarin91bccff2017-10-20 17:51:10 -0700256
Rahul Ravikumare92262f2018-02-07 18:48:15 -0800257 /**
258 * @return <code>true</code> if the {@link WorkSpec} has constraints.
259 */
260 public boolean hasConstraints() {
Sumir Katariab5728f42018-03-19 12:58:41 -0700261 return !Constraints.NONE.equals(constraints);
Rahul Ravikumare92262f2018-02-07 18:48:15 -0800262 }
263
Jan Clarin91bccff2017-10-20 17:51:10 -0700264 @Override
265 public boolean equals(Object o) {
Sumir Kataria86894df2018-03-06 15:11:16 -0800266 if (this == o) return true;
267 if (o == null || getClass() != o.getClass()) return false;
268
269 WorkSpec workSpec = (WorkSpec) o;
270
Sumir Katariab5728f42018-03-19 12:58:41 -0700271 if (initialDelay != workSpec.initialDelay) return false;
272 if (intervalDuration != workSpec.intervalDuration) return false;
273 if (flexDuration != workSpec.flexDuration) return false;
274 if (runAttemptCount != workSpec.runAttemptCount) return false;
275 if (backoffDelayDuration != workSpec.backoffDelayDuration) return false;
276 if (periodStartTime != workSpec.periodStartTime) return false;
277 if (minimumRetentionDuration != workSpec.minimumRetentionDuration) return false;
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -0700278 if (scheduleRequestedAt != workSpec.scheduleRequestedAt) return false;
Sumir Katariab5728f42018-03-19 12:58:41 -0700279 if (!id.equals(workSpec.id)) return false;
280 if (state != workSpec.state) return false;
281 if (!workerClassName.equals(workSpec.workerClassName)) return false;
282 if (inputMergerClassName != null ? !inputMergerClassName.equals(
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -0700283 workSpec.inputMergerClassName)
284 : workSpec.inputMergerClassName != null) {
Jan Clarin91bccff2017-10-20 17:51:10 -0700285 return false;
286 }
Sumir Kataria64e6bd82018-03-28 17:14:22 -0700287 if (!input.equals(workSpec.input)) return false;
Sumir Katariab5728f42018-03-19 12:58:41 -0700288 if (!output.equals(workSpec.output)) return false;
289 if (!constraints.equals(workSpec.constraints)) return false;
290 return backoffPolicy == workSpec.backoffPolicy;
Jan Clarin91bccff2017-10-20 17:51:10 -0700291 }
292
293 @Override
294 public int hashCode() {
Sumir Katariab5728f42018-03-19 12:58:41 -0700295 int result = id.hashCode();
296 result = 31 * result + state.hashCode();
297 result = 31 * result + workerClassName.hashCode();
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -0700298 result = 31 * result + (inputMergerClassName != null ? inputMergerClassName.hashCode() : 0);
Sumir Kataria64e6bd82018-03-28 17:14:22 -0700299 result = 31 * result + input.hashCode();
Sumir Katariab5728f42018-03-19 12:58:41 -0700300 result = 31 * result + output.hashCode();
301 result = 31 * result + (int) (initialDelay ^ (initialDelay >>> 32));
302 result = 31 * result + (int) (intervalDuration ^ (intervalDuration >>> 32));
303 result = 31 * result + (int) (flexDuration ^ (flexDuration >>> 32));
304 result = 31 * result + constraints.hashCode();
305 result = 31 * result + runAttemptCount;
306 result = 31 * result + backoffPolicy.hashCode();
307 result = 31 * result + (int) (backoffDelayDuration ^ (backoffDelayDuration >>> 32));
308 result = 31 * result + (int) (periodStartTime ^ (periodStartTime >>> 32));
Rahul Ravikumar9f91ee82018-03-20 17:33:38 -0700309 result = 31 * result + (int) (minimumRetentionDuration ^ (minimumRetentionDuration >>> 32));
310 result = 31 * result + (int) (scheduleRequestedAt ^ (scheduleRequestedAt >>> 32));
Jan Clarin91bccff2017-10-20 17:51:10 -0700311 return result;
312 }
Xyan Bhatnagarbbe9f312017-11-16 10:31:14 -0800313
314 @Override
315 public String toString() {
Sumir Katariab5728f42018-03-19 12:58:41 -0700316 return "{WorkSpec: " + id + "}";
Xyan Bhatnagarbbe9f312017-11-16 10:31:14 -0800317 }
Sumir Katariad2db35d2017-12-14 14:08:48 -0800318
319 /**
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800320 * A POJO containing the ID and state of a WorkSpec.
Sumir Katariad2db35d2017-12-14 14:08:48 -0800321 */
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800322 public static class IdAndState {
Sumir Katariad2db35d2017-12-14 14:08:48 -0800323
324 @ColumnInfo(name = "id")
325 public String id;
326
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800327 @ColumnInfo(name = "state")
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700328 public WorkInfo.State state;
Sumir Katariad2db35d2017-12-14 14:08:48 -0800329
330 @Override
331 public boolean equals(Object o) {
332 if (this == o) return true;
333 if (o == null || getClass() != o.getClass()) return false;
334
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800335 IdAndState that = (IdAndState) o;
Sumir Katariad2db35d2017-12-14 14:08:48 -0800336
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800337 if (state != that.state) return false;
Sumir Katariad2db35d2017-12-14 14:08:48 -0800338 return id.equals(that.id);
339 }
340
341 @Override
342 public int hashCode() {
343 int result = id.hashCode();
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800344 result = 31 * result + state.hashCode();
345 return result;
346 }
347 }
348
349 /**
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700350 * A POJO containing the ID, state, output, and tags of a WorkSpec.
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800351 */
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700352 public static class WorkInfoPojo {
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800353
354 @ColumnInfo(name = "id")
355 public String id;
356
357 @ColumnInfo(name = "state")
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700358 public WorkInfo.State state;
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800359
360 @ColumnInfo(name = "output")
Sumir Kataria64e6bd82018-03-28 17:14:22 -0700361 public Data output;
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800362
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700363 @Relation(
364 parentColumn = "id",
365 entityColumn = "work_spec_id",
366 entity = WorkTag.class,
367 projection = {"tag"})
368 public List<String> tags;
369
370 /**
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700371 * Converts this POJO to a {@link WorkInfo}.
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700372 *
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700373 * @return The {@link WorkInfo} represented by this POJO
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700374 */
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700375 public WorkInfo toWorkInfo() {
376 return new WorkInfo(UUID.fromString(id), state, output, tags);
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700377 }
378
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800379 @Override
380 public boolean equals(Object o) {
381 if (this == o) return true;
382 if (o == null || getClass() != o.getClass()) return false;
383
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700384 WorkInfoPojo that = (WorkInfoPojo) o;
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800385
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700386 if (id != null ? !id.equals(that.id) : that.id != null) return false;
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800387 if (state != that.state) return false;
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700388 if (output != null ? !output.equals(that.output) : that.output != null) return false;
389 return tags != null ? tags.equals(that.tags) : that.tags == null;
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800390 }
391
392 @Override
393 public int hashCode() {
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700394 int result = id != null ? id.hashCode() : 0;
395 result = 31 * result + (state != null ? state.hashCode() : 0);
Sumir Kataria9cf4f3d2018-02-06 09:57:51 -0800396 result = 31 * result + (output != null ? output.hashCode() : 0);
Sumir Katariacc5ae8c2018-03-12 12:57:46 -0700397 result = 31 * result + (tags != null ? tags.hashCode() : 0);
Sumir Katariad2db35d2017-12-14 14:08:48 -0800398 return result;
399 }
400 }
Sumir Kataria4401f792018-03-20 12:52:38 -0700401
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700402 public static final Function<List<WorkInfoPojo>, List<WorkInfo>> WORK_INFO_MAPPER =
403 new Function<List<WorkInfoPojo>, List<WorkInfo>>() {
Sumir Kataria4401f792018-03-20 12:52:38 -0700404 @Override
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700405 public List<WorkInfo> apply(List<WorkInfoPojo> input) {
Sumir Kataria4401f792018-03-20 12:52:38 -0700406 if (input == null) {
407 return null;
408 }
Rahul Ravikumar7f7ab612018-11-01 16:22:11 -0700409 List<WorkInfo> output = new ArrayList<>(input.size());
410 for (WorkInfoPojo in : input) {
411 output.add(in.toWorkInfo());
Sumir Kataria4401f792018-03-20 12:52:38 -0700412 }
413 return output;
414 }
415 };
Sumir Kataria904ba122017-09-25 13:05:49 -0700416}