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 package androidx.work 17 18 import android.annotation.SuppressLint 19 import android.net.NetworkRequest 20 import android.net.Uri 21 import android.os.Build 22 import androidx.annotation.RequiresApi 23 import androidx.annotation.RestrictTo 24 import androidx.room.ColumnInfo 25 import androidx.room.Ignore 26 import androidx.work.impl.utils.NetworkRequest30 27 import androidx.work.impl.utils.NetworkRequestCompat 28 import androidx.work.impl.utils.toMillisCompat 29 import java.time.Duration 30 import java.util.concurrent.TimeUnit 31 32 /** 33 * A specification of the requirements that need to be met before a [WorkRequest] can run. By 34 * default, WorkRequests do not have any requirements and can run immediately. By adding 35 * requirements, you can make sure that work only runs in certain situations - for example, when you 36 * have an unmetered network and are charging. 37 */ 38 class Constraints { 39 /** The type of network required for the work to run. */ 40 @ColumnInfo(name = "required_network_type") val requiredNetworkType: NetworkType 41 42 /** 43 * [NetworkRequest] required for work to run on. It is used only the API levels >= 28 (Android 44 * P). For the older API levels, [requiredNetworkType] will be used instead on the older 45 * platforms and this property will be `null`. 46 * 47 * `NetworkRequest`-s with `NetworkSpecifier` set aren't supported, as well as `NetworkRequest` 48 * with `setIncludeOtherUidNetworks` set. passed. 49 */ 50 @get:RequiresApi(21) // NetworkRequest class is available since 21 51 val requiredNetworkRequest: NetworkRequest? 52 get() = requiredNetworkRequestCompat.networkRequest 53 54 @ColumnInfo(name = "required_network_request", defaultValue = "x''") 55 internal val requiredNetworkRequestCompat: NetworkRequestCompat 56 57 @ColumnInfo(name = "requires_charging") private val requiresCharging: Boolean 58 59 @ColumnInfo(name = "requires_device_idle") private val requiresDeviceIdle: Boolean 60 61 @ColumnInfo(name = "requires_battery_not_low") private val requiresBatteryNotLow: Boolean 62 63 @ColumnInfo(name = "requires_storage_not_low") private val requiresStorageNotLow: Boolean 64 65 /** 66 * The delay in milliseconds that is allowed from the time a `content:` [Uri] change is detected 67 * to the time when the [WorkRequest] is scheduled. If there are more changes during this time, 68 * the delay will be reset to the start of the most recent change. This functionality is 69 * identical to the one found in `JobScheduler` and is described in 70 * [android.app.job.JobInfo.Builder.setTriggerContentUpdateDelay] 71 */ 72 @get:RequiresApi(24) 73 @ColumnInfo(name = "trigger_content_update_delay") 74 val contentTriggerUpdateDelayMillis: Long 75 76 /** 77 * The maximum delay in milliseconds that is allowed from the first time a `content:` [Uri] 78 * change is detected to the time when the [WorkRequest] is scheduled. This functionality is 79 * identical to the one found in `JobScheduler` and is described in 80 * [android.app.job.JobInfo.Builder.setTriggerContentMaxDelay]. 81 */ 82 @get:RequiresApi(24) 83 @ColumnInfo(name = "trigger_max_content_delay") 84 val contentTriggerMaxDelayMillis: Long 85 86 /** 87 * Set of [ContentUriTrigger]. [WorkRequest] will run when a local `content:` [Uri] of one of 88 * the triggers in the set is updated. This functionality is identical to the one found in 89 * `JobScheduler` and is described in [android.app.job.JobInfo.Builder.addTriggerContentUri]. 90 */ 91 @ColumnInfo(name = "content_uri_triggers") 92 @get:RequiresApi(24) 93 val contentUriTriggers: Set<ContentUriTrigger> 94 95 /** 96 * Constructs [Constraints]. 97 * 98 * @param requiredNetworkType The type of network required for the work to run. The default 99 * value is [NetworkType.NOT_REQUIRED]. 100 * @param requiresCharging whether device should be charging for the [WorkRequest] to run. The 101 * default value is `false`. 102 * @param requiresBatteryNotLow whether device battery should be at an acceptable level for the 103 * [WorkRequest] to run. The default value is `false`. 104 * @param requiresStorageNotLow whether the device's available storage should be at an 105 * acceptable level for the [WorkRequest] to run. The default value is `false`. 106 */ 107 @Ignore 108 @SuppressLint("NewApi") 109 constructor( 110 requiredNetworkType: NetworkType = NetworkType.NOT_REQUIRED, 111 requiresCharging: Boolean = false, 112 requiresBatteryNotLow: Boolean = false, 113 requiresStorageNotLow: Boolean = false, 114 ) : this( 115 requiredNetworkType = requiredNetworkType, 116 requiresCharging = requiresCharging, 117 requiresStorageNotLow = requiresStorageNotLow, 118 requiresBatteryNotLow = requiresBatteryNotLow, 119 requiresDeviceIdle = false 120 ) 121 122 /** 123 * Constructs [Constraints]. 124 * 125 * @param requiredNetworkType The type of network required for the work to run. The default 126 * value is [NetworkType.NOT_REQUIRED]. 127 * @param requiresCharging whether device should be charging for the [WorkRequest] to run. The 128 * default value is `false`. 129 * @param requiresDeviceIdle whether device should be idle for the [WorkRequest] to run. The 130 * default value is `false`. 131 * @param requiresBatteryNotLow whether device battery should be at an acceptable level for the 132 * [WorkRequest] to run. The default value is `false`. 133 * @param requiresStorageNotLow whether the device's available storage should be at an 134 * acceptable level for the [WorkRequest] to run. The default value is `false`. 135 */ 136 @Ignore 137 @SuppressLint("NewApi") 138 @RequiresApi(23) // requiresDeviceIdle is supported since API 23 139 constructor( 140 requiredNetworkType: NetworkType = NetworkType.NOT_REQUIRED, 141 requiresCharging: Boolean = false, 142 requiresDeviceIdle: Boolean = false, 143 requiresBatteryNotLow: Boolean = false, 144 requiresStorageNotLow: Boolean = false, 145 ) : this( 146 requiredNetworkType = requiredNetworkType, 147 requiresCharging = requiresCharging, 148 requiresDeviceIdle = requiresDeviceIdle, 149 requiresBatteryNotLow = requiresBatteryNotLow, 150 requiresStorageNotLow = requiresStorageNotLow, 151 contentTriggerUpdateDelayMillis = -1, 152 ) 153 154 /** 155 * Constructs [Constraints]. 156 * 157 * @param requiredNetworkType The type of network required for the work to run. The default 158 * value is [NetworkType.NOT_REQUIRED]. 159 * @param requiresCharging whether device should be charging for the [WorkRequest] to run. The 160 * default value is `false`. 161 * @param requiresDeviceIdle whether device should be idle for the [WorkRequest] to run. The 162 * default value is `false`. 163 * @param requiresBatteryNotLow whether device battery should be at an acceptable level for the 164 * [WorkRequest] to run. The default value is `false`. 165 * @param requiresStorageNotLow whether the device's available storage should be at an 166 * acceptable level for the [WorkRequest] to run. The default value is `false`. 167 * @param contentTriggerUpdateDelayMillis the delay in milliseconds that is allowed from the 168 * time a `content:` [Uri] change is detected to the time when the [WorkRequest] is scheduled. 169 * If there are more changes during this time, the delay will be reset to the start of the 170 * most recent change. This functionality is identical to the one found in `JobScheduler` and 171 * is described in [android.app.job.JobInfo.Builder.setTriggerContentUpdateDelay] 172 * @param contentTriggerMaxDelayMillis the maximum delay in milliseconds that is allowed from 173 * the first time a `content:` [Uri] change is detected to the time when the [WorkRequest] is 174 * scheduled. This functionality is identical to the one found in `JobScheduler` and is 175 * described in [android.app.job.JobInfo.Builder.setTriggerContentMaxDelay]. 176 * @param contentUriTriggers set of [ContentUriTrigger]. [WorkRequest] will run when a local 177 * `content:` [Uri] of one of the triggers in the set is updated. This functionality is 178 * identical to the one found in `JobScheduler` and is described in 179 * [android.app.job.JobInfo.Builder.addTriggerContentUri]. 180 */ 181 @Ignore 182 @RequiresApi(24) 183 constructor( 184 requiredNetworkType: NetworkType = NetworkType.NOT_REQUIRED, 185 requiresCharging: Boolean = false, 186 requiresDeviceIdle: Boolean = false, 187 requiresBatteryNotLow: Boolean = false, 188 requiresStorageNotLow: Boolean = false, 189 contentTriggerUpdateDelayMillis: Long = -1, 190 contentTriggerMaxDelayMillis: Long = -1, 191 contentUriTriggers: Set<ContentUriTrigger> = setOf(), 192 ) { 193 this.requiredNetworkRequestCompat = NetworkRequestCompat() 194 this.requiredNetworkType = requiredNetworkType 195 this.requiresCharging = requiresCharging 196 this.requiresDeviceIdle = requiresDeviceIdle 197 this.requiresBatteryNotLow = requiresBatteryNotLow 198 this.requiresStorageNotLow = requiresStorageNotLow 199 this.contentTriggerUpdateDelayMillis = contentTriggerUpdateDelayMillis 200 this.contentTriggerMaxDelayMillis = contentTriggerMaxDelayMillis 201 this.contentUriTriggers = contentUriTriggers 202 } 203 204 internal constructor( 205 requiredNetworkRequestCompat: NetworkRequestCompat, 206 requiredNetworkType: NetworkType = NetworkType.NOT_REQUIRED, 207 requiresCharging: Boolean = false, 208 requiresDeviceIdle: Boolean = false, 209 requiresBatteryNotLow: Boolean = false, 210 requiresStorageNotLow: Boolean = false, 211 contentTriggerUpdateDelayMillis: Long = -1, 212 contentTriggerMaxDelayMillis: Long = -1, 213 contentUriTriggers: Set<ContentUriTrigger> = setOf(), 214 ) { 215 this.requiredNetworkRequestCompat = requiredNetworkRequestCompat 216 this.requiredNetworkType = requiredNetworkType 217 this.requiresCharging = requiresCharging 218 this.requiresDeviceIdle = requiresDeviceIdle 219 this.requiresBatteryNotLow = requiresBatteryNotLow 220 this.requiresStorageNotLow = requiresStorageNotLow 221 this.contentTriggerUpdateDelayMillis = contentTriggerUpdateDelayMillis 222 this.contentTriggerMaxDelayMillis = contentTriggerMaxDelayMillis 223 this.contentUriTriggers = contentUriTriggers 224 } 225 226 @SuppressLint("NewApi") // just copy everything 227 constructor(other: Constraints) { 228 requiresCharging = other.requiresCharging 229 requiresDeviceIdle = other.requiresDeviceIdle 230 requiredNetworkRequestCompat = other.requiredNetworkRequestCompat 231 requiredNetworkType = other.requiredNetworkType 232 requiresBatteryNotLow = other.requiresBatteryNotLow 233 requiresStorageNotLow = other.requiresStorageNotLow 234 contentUriTriggers = other.contentUriTriggers 235 contentTriggerUpdateDelayMillis = other.contentTriggerUpdateDelayMillis 236 contentTriggerMaxDelayMillis = other.contentTriggerMaxDelayMillis 237 } 238 239 /** @return `true` if the work should only execute while the device is charging */ requiresChargingnull240 fun requiresCharging(): Boolean { 241 return requiresCharging 242 } 243 244 /** @return `true` if the work should only execute while the device is idle */ 245 @RequiresApi(23) requiresDeviceIdlenull246 fun requiresDeviceIdle(): Boolean { 247 return requiresDeviceIdle 248 } 249 250 /** @return `true` if the work should only execute when the battery isn't low */ requiresBatteryNotLownull251 fun requiresBatteryNotLow(): Boolean { 252 return requiresBatteryNotLow 253 } 254 255 /** @return `true` if the work should only execute when the storage isn't low */ requiresStorageNotLownull256 fun requiresStorageNotLow(): Boolean { 257 return requiresStorageNotLow 258 } 259 260 /** @return `true` if [ContentUriTrigger] is not empty */ 261 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) hasContentUriTriggersnull262 fun hasContentUriTriggers(): Boolean { 263 return Build.VERSION.SDK_INT < 24 || contentUriTriggers.isNotEmpty() 264 } 265 266 // just use all properties in equals, no actual harm in accessing properties annotated by 267 // RequiresApi(...) 268 @SuppressLint("NewApi") equalsnull269 override fun equals(other: Any?): Boolean { 270 if (this === other) return true 271 if (other == null || javaClass != other.javaClass) return false 272 val that = other as Constraints 273 if (requiresCharging != that.requiresCharging) return false 274 if (requiresDeviceIdle != that.requiresDeviceIdle) return false 275 if (requiresBatteryNotLow != that.requiresBatteryNotLow) return false 276 if (requiresStorageNotLow != that.requiresStorageNotLow) return false 277 if (contentTriggerUpdateDelayMillis != that.contentTriggerUpdateDelayMillis) return false 278 if (contentTriggerMaxDelayMillis != that.contentTriggerMaxDelayMillis) return false 279 if (requiredNetworkRequest != that.requiredNetworkRequest) return false 280 return if (requiredNetworkType != that.requiredNetworkType) false 281 else contentUriTriggers == that.contentUriTriggers 282 } 283 284 // just use all properties in hashCode, no actual harm in accessing properties annotated by 285 // RequiresApi(...) 286 @SuppressLint("NewApi") hashCodenull287 override fun hashCode(): Int { 288 var result = requiredNetworkType.hashCode() 289 result = 31 * result + if (requiresCharging) 1 else 0 290 result = 31 * result + if (requiresDeviceIdle) 1 else 0 291 result = 31 * result + if (requiresBatteryNotLow) 1 else 0 292 result = 31 * result + if (requiresStorageNotLow) 1 else 0 293 result = 294 31 * result + 295 (contentTriggerUpdateDelayMillis xor (contentTriggerUpdateDelayMillis ushr 32)) 296 .toInt() 297 result = 298 31 * result + 299 (contentTriggerMaxDelayMillis xor (contentTriggerMaxDelayMillis ushr 32)).toInt() 300 result = 31 * result + contentUriTriggers.hashCode() 301 result = 31 * result + requiredNetworkRequest.hashCode() 302 return result 303 } 304 305 // just use all properties in toString, no actual harm in accessing properties annotated by 306 // RequiresApi(...) 307 @SuppressLint("NewApi") toStringnull308 override fun toString(): String { 309 return "Constraints{" + 310 "requiredNetworkType=$requiredNetworkType, " + 311 "requiresCharging=$requiresCharging, " + 312 "requiresDeviceIdle=$requiresDeviceIdle, " + 313 "requiresBatteryNotLow=$requiresBatteryNotLow, " + 314 "requiresStorageNotLow=$requiresStorageNotLow, " + 315 "contentTriggerUpdateDelayMillis=$contentTriggerUpdateDelayMillis, " + 316 "contentTriggerMaxDelayMillis=$contentTriggerMaxDelayMillis, " + 317 "contentUriTriggers=$contentUriTriggers, " + 318 "}" 319 } 320 321 /** A Builder for a [Constraints] object. */ 322 class Builder { 323 private var requiresCharging = false 324 private var requiresDeviceIdle = false 325 private var requiredNetworkRequest: NetworkRequestCompat = NetworkRequestCompat() 326 private var requiredNetworkType = NetworkType.NOT_REQUIRED 327 private var requiresBatteryNotLow = false 328 private var requiresStorageNotLow = false 329 330 // Same defaults as JobInfo 331 private var triggerContentUpdateDelay: Long = -1 332 private var triggerContentMaxDelay: Long = -1 333 private var contentUriTriggers = mutableSetOf<ContentUriTrigger>() 334 335 constructor() { 336 // default public constructor 337 } 338 339 /** */ 340 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 341 constructor(constraints: Constraints) { 342 requiresCharging = constraints.requiresCharging() 343 requiresDeviceIdle = Build.VERSION.SDK_INT >= 23 && constraints.requiresDeviceIdle() 344 requiredNetworkType = constraints.requiredNetworkType 345 requiresBatteryNotLow = constraints.requiresBatteryNotLow() 346 requiresStorageNotLow = constraints.requiresStorageNotLow() 347 if (Build.VERSION.SDK_INT >= 24) { 348 triggerContentUpdateDelay = constraints.contentTriggerUpdateDelayMillis 349 triggerContentMaxDelay = constraints.contentTriggerMaxDelayMillis 350 contentUriTriggers = constraints.contentUriTriggers.toMutableSet() 351 } 352 } 353 354 /** 355 * Sets whether device should be charging for the [WorkRequest] to run. The default value is 356 * `false`. 357 * 358 * @param requiresCharging `true` if device must be charging for the work to run 359 * @return The current [Builder] 360 */ setRequiresChargingnull361 fun setRequiresCharging(requiresCharging: Boolean): Builder { 362 this.requiresCharging = requiresCharging 363 return this 364 } 365 366 /** 367 * Sets whether device should be idle for the [WorkRequest] to run. The default value is 368 * `false`. 369 * 370 * @param requiresDeviceIdle `true` if device must be idle for the work to run 371 * @return The current [Builder] 372 */ 373 @RequiresApi(23) setRequiresDeviceIdlenull374 fun setRequiresDeviceIdle(requiresDeviceIdle: Boolean): Builder { 375 this.requiresDeviceIdle = requiresDeviceIdle 376 return this 377 } 378 379 /** 380 * Sets whether device should have a particular [NetworkType] for the [WorkRequest] to run. 381 * The default value is [NetworkType.NOT_REQUIRED]. 382 * 383 * @param networkType The type of network required for the work to run 384 * @return The current [Builder] 385 */ setRequiredNetworkTypenull386 fun setRequiredNetworkType(networkType: NetworkType): Builder { 387 requiredNetworkType = networkType 388 requiredNetworkRequest = NetworkRequestCompat() 389 return this 390 } 391 392 /** 393 * Sets whether device should have a particular [NetworkRequest] for the [WorkRequest] to 394 * run on the API levels >= 28 (Android P). For the older API levels, `networkType` will be 395 * used instead on the older platforms. 396 * 397 * `NetworkRequest` with `NetworkSpecifier` set aren't supported, as well as 398 * `NetworkRequest` with `setIncludeOtherUidNetworks` set. [IllegalArgumentException] will 399 * be thrown if such requests are passed. 400 * 401 * @param networkRequest 402 * @param networkType The type of network required for t 403 * @return The current [Builder] 404 */ 405 @RequiresApi(21) setRequiredNetworkRequestnull406 fun setRequiredNetworkRequest( 407 networkRequest: NetworkRequest, 408 networkType: NetworkType 409 ): Builder { 410 if (Build.VERSION.SDK_INT >= 28) { 411 if ( 412 Build.VERSION.SDK_INT >= 31 && 413 NetworkRequest30.getNetworkSpecifier(networkRequest) != null 414 ) { 415 throw IllegalArgumentException( 416 "NetworkRequests with NetworkSpecifiers set aren't supported." 417 ) 418 } 419 requiredNetworkRequest = NetworkRequestCompat(networkRequest) 420 requiredNetworkType = NetworkType.NOT_REQUIRED 421 } else { 422 requiredNetworkType = networkType 423 } 424 return this 425 } 426 427 /** 428 * Sets whether device battery should be at an acceptable level for the [WorkRequest] to 429 * run. The default value is `false`. 430 * 431 * @param requiresBatteryNotLow `true` if the battery should be at an acceptable level for 432 * the work to run 433 * @return The current [Builder] 434 */ setRequiresBatteryNotLownull435 fun setRequiresBatteryNotLow(requiresBatteryNotLow: Boolean): Builder { 436 this.requiresBatteryNotLow = requiresBatteryNotLow 437 return this 438 } 439 440 /** 441 * Sets whether the device's available storage should be at an acceptable level for the 442 * [WorkRequest] to run. The default value is `false`. 443 * 444 * @param requiresStorageNotLow `true` if the available storage should not be below a a 445 * critical threshold for the work to run 446 * @return The current [Builder] 447 */ setRequiresStorageNotLownull448 fun setRequiresStorageNotLow(requiresStorageNotLow: Boolean): Builder { 449 this.requiresStorageNotLow = requiresStorageNotLow 450 return this 451 } 452 453 /** 454 * Sets whether the [WorkRequest] should run when a local `content:` [Uri] is updated. This 455 * functionality is identical to the one found in `JobScheduler` and is described in 456 * `JobInfo.Builder#addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri)`. 457 * 458 * @param uri The local `content:` Uri to observe 459 * @param triggerForDescendants `true` if any changes in descendants cause this 460 * [WorkRequest] to run 461 * @return The current [Builder] 462 */ 463 @RequiresApi(24) addContentUriTriggernull464 fun addContentUriTrigger(uri: Uri, triggerForDescendants: Boolean): Builder { 465 contentUriTriggers.add(ContentUriTrigger(uri, triggerForDescendants)) 466 return this 467 } 468 469 /** 470 * Sets the delay that is allowed from the time a `content:` [Uri] change is detected to the 471 * time when the [WorkRequest] is scheduled. If there are more changes during this time, the 472 * delay will be reset to the start of the most recent change. This functionality is 473 * identical to the one found in `JobScheduler` and is described in 474 * `JobInfo.Builder#setTriggerContentUpdateDelay(long)`. 475 * 476 * @param duration The length of the delay in `timeUnit` units 477 * @param timeUnit The units of time for `duration` 478 * @return The current [Builder] 479 */ 480 @RequiresApi(24) setTriggerContentUpdateDelaynull481 fun setTriggerContentUpdateDelay(duration: Long, timeUnit: TimeUnit): Builder { 482 triggerContentUpdateDelay = timeUnit.toMillis(duration) 483 return this 484 } 485 486 /** 487 * Sets the delay that is allowed from the time a `content:` [Uri] change is detected to the 488 * time when the [WorkRequest] is scheduled. If there are more changes during this time, the 489 * delay will be reset to the start of the most recent change. This functionality is 490 * identical to the one found in `JobScheduler` and is described in 491 * `JobInfo.Builder#setTriggerContentUpdateDelay(long)`. 492 * 493 * @param duration The length of the delay 494 * @return The current [Builder] 495 */ 496 @RequiresApi(26) setTriggerContentUpdateDelaynull497 fun setTriggerContentUpdateDelay(duration: Duration): Builder { 498 triggerContentUpdateDelay = duration.toMillisCompat() 499 return this 500 } 501 502 /** 503 * Sets the maximum delay that is allowed from the first time a `content:` [Uri] change is 504 * detected to the time when the [WorkRequest] is scheduled. This functionality is identical 505 * to the one found in `JobScheduler` and is described in 506 * `JobInfo.Builder#setTriggerContentMaxDelay(long)`. 507 * 508 * @param duration The length of the delay in `timeUnit` units 509 * @param timeUnit The units of time for `duration` 510 * @return The current [Builder] 511 */ 512 @RequiresApi(24) setTriggerContentMaxDelaynull513 fun setTriggerContentMaxDelay(duration: Long, timeUnit: TimeUnit): Builder { 514 triggerContentMaxDelay = timeUnit.toMillis(duration) 515 return this 516 } 517 518 /** 519 * Sets the maximum delay that is allowed from the first time a `content:` [Uri] change is 520 * detected to the time when the [WorkRequest] is scheduled. This functionality is identical 521 * to the one found in `JobScheduler` and is described in 522 * `JobInfo.Builder#setTriggerContentMaxDelay(long)`. 523 * 524 * @param duration The length of the delay 525 * @return The current [Builder] 526 */ 527 @RequiresApi(26) setTriggerContentMaxDelaynull528 fun setTriggerContentMaxDelay(duration: Duration): Builder { 529 triggerContentMaxDelay = duration.toMillisCompat() 530 return this 531 } 532 533 /** 534 * Generates the [Constraints] from this Builder. 535 * 536 * @return The [Constraints] specified by this Builder 537 */ buildnull538 fun build(): Constraints { 539 val contentUriTriggers: Set<ContentUriTrigger> 540 val triggerContentUpdateDelay: Long 541 val triggerMaxContentDelay: Long 542 if (Build.VERSION.SDK_INT >= 24) { 543 contentUriTriggers = this.contentUriTriggers.toSet() 544 triggerContentUpdateDelay = this.triggerContentUpdateDelay 545 triggerMaxContentDelay = triggerContentMaxDelay 546 } else { 547 contentUriTriggers = emptySet() 548 triggerContentUpdateDelay = -1 549 triggerMaxContentDelay = -1 550 } 551 552 @Suppress("NewApi") 553 return Constraints( 554 requiredNetworkRequestCompat = requiredNetworkRequest, 555 requiredNetworkType = requiredNetworkType, 556 requiresCharging = requiresCharging, 557 requiresDeviceIdle = Build.VERSION.SDK_INT >= 23 && requiresDeviceIdle, 558 requiresBatteryNotLow = requiresBatteryNotLow, 559 requiresStorageNotLow = requiresStorageNotLow, 560 contentTriggerMaxDelayMillis = triggerMaxContentDelay, 561 contentTriggerUpdateDelayMillis = triggerContentUpdateDelay, 562 contentUriTriggers = contentUriTriggers, 563 ) 564 } 565 } 566 567 /** 568 * This class describes a content uri trigger on the [WorkRequest]: it should run when a local 569 * `content:` [Uri] is updated. This functionality is identical to the one found in 570 * `JobScheduler` and is described in 571 * `JobInfo.Builder#addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri)`. 572 * 573 * @property uri The local `content:` Uri to observe 574 * @property isTriggeredForDescendants `true` if trigger also applies to descendants of the 575 * [Uri] 576 */ 577 class ContentUriTrigger(val uri: Uri, val isTriggeredForDescendants: Boolean) { equalsnull578 override fun equals(other: Any?): Boolean { 579 if (this === other) return true 580 if (javaClass != other?.javaClass) return false 581 582 other as ContentUriTrigger 583 584 if (uri != other.uri) return false 585 if (isTriggeredForDescendants != other.isTriggeredForDescendants) return false 586 587 return true 588 } 589 hashCodenull590 override fun hashCode(): Int { 591 var result = uri.hashCode() 592 result = 31 * result + isTriggeredForDescendants.hashCode() 593 return result 594 } 595 } 596 597 companion object { 598 /** Represents a Constraints object with no requirements. */ 599 @JvmField val NONE = Constraints() 600 } 601 } 602 603 internal const val CONSTRAINTS_COLUMNS = 604 "required_network_type, required_network_request, requires_charging, " + 605 "requires_device_idle, requires_battery_not_low, requires_storage_not_low, " + 606 "trigger_content_update_delay, trigger_max_content_delay, content_uri_triggers" 607