How does WorkManager's setRequiresDeviceIdle(true) work?
Asked Answered
J

0

7

I need to run a specific work only if the device is not in use. However, I don't fully understand how the .setRequiresDeviceIdle() constraint works.

I'm scheduling a worker like this:

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresBatteryNotLow(true)
    .setRequiresStorageNotLow(true)
    .setRequiresDeviceIdle(true)
    .build()

val networkWorkRequest = PeriodicWorkRequestBuilder<NetworkWorker>(15, TimeUnit.MINUTES)
    .addTag(NetworkWorker.TAG)
    .setInitialDelay(15, TimeUnit.SECONDS)
    .setConstraints(constraints)
    .build()

WorkManager.getInstance(context)
    .enqueueUniquePeriodicWork(NetworkWorker.TAG, ExistingPeriodicWorkPolicy.REPLACE, networkWorkRequest)

Please note that the device is fully charged, has enough storage and an available internet connection at all times (meaning all first 3 constraints were met).

I've tried not touching the device for hours, closing all apps, even triggered doze mode (and then maintenance window) via ADB (with adb shell dumpsys deviceidle force-idle and then adb shell dumpsys deviceidle step), but nothing seems to work (According to the docs this "idle" is not the same as doze mode, but I decided to give it a shot it anyway).

As you can see I've scheduled the job as periodic, just for the sake of checking if it would make any difference (in fact I only need a one-time worker). I left the device over night, and eventually the worker ran (these are some logs I'm writing to a file in the sd card):

1620688536155,2021.05.11 00:15:36.155,DEBUG,PRETTY_LOGGER,Enqueueing worker with id 931d2b1f-85f4-445f-a889-832fdd945752
1620712213970,2021.05.11 06:50:13.970,DEBUG,PRETTY_LOGGER,Running background work… --- job started running
1620712224898,2021.05.11 06:50:24.898,DEBUG,PRETTY_LOGGER,Response is: IT WORKS
1620712224899,2021.05.11 06:50:24.899,DEBUG,PRETTY_LOGGER,Done! --- job finished

I'm fine if my job runs at least once over night, because it's meant for triggering an update process, so I really need the device to be idle when it happens. In any case, I'd like to understand how to be sure that it will run, and how to mimic that for testing purposes (like we can do with doze mode, for example).

I've read a lot about it in the docs (WorkManager will use JobScheduler on API 23+, which is the case), on Medium (which says that "idle" is when the device "hasn’t been used in a little while") and went through a lot of SO questions, nobody seems to know how to properly test this.

Given the above, my questions are:

  1. Can I force the device into a state where it is considered as "idle" by WorkManager to properly validate my work gets done?
  2. Is there a good place to look for how/when WorkManager considers the device as being idle?
Jaeger answered 11/5, 2021 at 10:24 Comment(1)
I think i found sth: aosp.opersys.com/xref/android-10.0.0_r36/xref/frameworks/base/…Tipi

© 2022 - 2024 — McMap. All rights reserved.