130 lines
7.1 KiB
Diff
130 lines
7.1 KiB
Diff
![]() |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
|
||
|
Date: Thu, 7 Jul 2022 09:28:40 +0300
|
||
|
Subject: [PATCH] DeviceIdleJobsController: don't ignore whitelisted system
|
||
|
apps
|
||
|
|
||
|
Only user app IDs were written to `mDeviceIdleWhitelistAppIds`, both initially and when
|
||
|
`PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED` broadcast was received. All other places that
|
||
|
listen to that broadcast retrieve both user and system app IDs.
|
||
|
|
||
|
The only place where `mDeviceIdleWhitelistAppIds` array is checked is in `isWhitelistedLocked()`,
|
||
|
which is called only by `updateTaskStateLocked()` to check whether the app is on the device idle whitelist.
|
||
|
|
||
|
It's not clear why DeviceIdleJobsController ignores system apps.
|
||
|
File level comment doesn't mention the distinction between system and user apps:
|
||
|
"When device is dozing, set constraint for all jobs, except whitelisted apps, as not satisfied."
|
||
|
Comment for isWhitelistedLocked() does, however:
|
||
|
"Checks if the given job's scheduling app id exists in the device idle user whitelist."
|
||
|
However, that method is called for both system and user apps, and returns false for system apps
|
||
|
because only whitelist of user apps is checked. This leads to long delays for jobs that were
|
||
|
submitted by whitelisted system apps when device is in the Doze mode. No such delays happen with
|
||
|
whitelisted user apps.
|
||
|
|
||
|
Other places use a different naming for array of app IDs that includes only user apps,
|
||
|
eg `mDeviceIdleWhitelistUserAppIds`, not `mDeviceIdleWhitelistAppIds`.
|
||
|
|
||
|
I've looked through the Git history of DeviceIdleJobsController and JobSchedulerService, but didn't
|
||
|
find a reason for this behavior. Perhaps, system apps were exempted from device idle JobScheduler
|
||
|
restricitions in some other place previously, or this was a bug from the start.
|
||
|
|
||
|
Tested on an emulator with the Messaging app, which uses JobScheduler
|
||
|
during processing of incoming SMS:
|
||
|
1. Check that Messaging app is on system deviceidle whitelist:
|
||
|
```
|
||
|
$ dumpsys deviceidle whitelist | grep com.android.messaging
|
||
|
system-excidle,com.android.messaging,10090
|
||
|
system,com.android.messaging,10090
|
||
|
```
|
||
|
2. Simulate sending an SMS: it appears immediately
|
||
|
3. Simulate Doze mode: `$ dumpsys deviceidle force-idle`
|
||
|
4. Simulate sending an SMS again. Message doesn't appear, even if the Messaging app is open
|
||
|
5. Exit Doze mode: `$ dumpsys deviceidle unforce`. All pending messages appear immediately
|
||
|
6. Add Messaging app to the user whitelist:
|
||
|
```
|
||
|
$ dumpsys deviceidle whitelist +com.android.messaging
|
||
|
$ dumpsys deviceidle whitelist | grep com.android.messaging
|
||
|
system-excidle,com.android.messaging,10090
|
||
|
system,com.android.messaging,10090
|
||
|
user,com.android.messaging,10090
|
||
|
```
|
||
|
7. Simulate Doze mode again: `$ dumpsys deviceidle force-idle`
|
||
|
8. Simulate sending an SMS, note that it appears immediately this time
|
||
|
|
||
|
Also made a test system app to make sure that this issue isn't caused by low targetSdk of the
|
||
|
Messaging app (it targets SDK 24). Same issue with targetSdk 32 app.
|
||
|
|
||
|
In both cases, applying this patch fixes the issue.
|
||
|
---
|
||
|
.../java/com/android/server/DeviceIdleInternal.java | 2 +-
|
||
|
.../java/com/android/server/DeviceIdleController.java | 6 +++---
|
||
|
.../server/job/controllers/DeviceIdleJobsController.java | 6 +++---
|
||
|
3 files changed, 7 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
|
||
|
index 6475f5706a6d..b3e2629af684 100644
|
||
|
--- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
|
||
|
+++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java
|
||
|
@@ -46,7 +46,7 @@ public interface DeviceIdleInternal {
|
||
|
|
||
|
boolean isAppOnWhitelist(int appid);
|
||
|
|
||
|
- int[] getPowerSaveWhitelistUserAppIds();
|
||
|
+ int[] getPowerSaveWhitelistAppIds();
|
||
|
|
||
|
int[] getPowerSaveTempWhitelistAppIds();
|
||
|
|
||
|
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
|
||
|
index ac58f3d6a94d..ad656425af00 100644
|
||
|
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
|
||
|
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
|
||
|
@@ -1812,14 +1812,14 @@ public class DeviceIdleController extends SystemService
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
- * Returns the array of app ids whitelisted by user. Take care not to
|
||
|
+ * Returns the array of whitelisted app ids. Take care not to
|
||
|
* modify this, as it is a reference to the original copy. But the reference
|
||
|
* can change when the list changes, so it needs to be re-acquired when
|
||
|
* {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
|
||
|
*/
|
||
|
@Override
|
||
|
- public int[] getPowerSaveWhitelistUserAppIds() {
|
||
|
- return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
|
||
|
+ public int[] getPowerSaveWhitelistAppIds() {
|
||
|
+ return DeviceIdleController.this.getAppIdWhitelistInternal();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
|
||
|
index 01f5fa62f889..4b1a830b319f 100644
|
||
|
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
|
||
|
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
|
||
|
@@ -88,7 +88,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||
|
case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED:
|
||
|
synchronized (mLock) {
|
||
|
mDeviceIdleWhitelistAppIds =
|
||
|
- mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
|
||
|
+ mLocalDeviceIdleController.getPowerSaveWhitelistAppIds();
|
||
|
if (DEBUG) {
|
||
|
Slog.d(TAG, "Got whitelist "
|
||
|
+ Arrays.toString(mDeviceIdleWhitelistAppIds));
|
||
|
@@ -124,7 +124,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||
|
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||
|
mLocalDeviceIdleController =
|
||
|
LocalServices.getService(DeviceIdleInternal.class);
|
||
|
- mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
|
||
|
+ mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistAppIds();
|
||
|
mPowerSaveTempWhitelistAppIds =
|
||
|
mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
|
||
|
mDeviceIdleUpdateFunctor = new DeviceIdleUpdateFunctor();
|
||
|
@@ -188,7 +188,7 @@ public final class DeviceIdleJobsController extends StateController {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
- * Checks if the given job's scheduling app id exists in the device idle user whitelist.
|
||
|
+ * Checks if the given job's scheduling app id exists in the device idle whitelist.
|
||
|
*/
|
||
|
boolean isWhitelistedLocked(JobStatus job) {
|
||
|
return Arrays.binarySearch(mDeviceIdleWhitelistAppIds,
|