diff options
author | Tommy Webb <tommy@calyxinstitute.org> | 2023-03-13 16:16:58 -0400 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2023-04-20 00:08:54 +0800 |
commit | 31cbe9d5d2e39d55b46e5856eaa8a8f7a9c36919 (patch) | |
tree | 6b0eb9667af386007503a5d048a54b1d983392d0 | |
parent | 6280c835c16fad823e80f7b069af97b939601ffc (diff) |
JobScheduler: Respect allow-in-power-save perm
Apps like Messaging may be allowlisted to be unaffected by doze mode
using the allow-in-power-save permission, but prior to this change,
their jobs are still restricted from running when the device is idle,
leading to delayed processing. On the other hand, jobs scheduled by
packages that are user-exempted via the "Unrestricted" app battery
usage option do not experience such delays. This change causes system-
exempted packages to be treated the same as user-exempted packages.
Issue: calyxos#1525
Bug: 223643513
Test: CtsJobSchedulerTestCases
Change-Id: I6d95b3940e536e93aae4b2b48706069e964bdb99
6 files changed, 69 insertions, 4 deletions
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java index caf7e7f4a4ed..7ec603de40fd 100644 --- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java @@ -73,6 +73,8 @@ public interface DeviceIdleInternal { boolean isAppOnWhitelist(int appid); + int[] getPowerSaveWhitelistSystemAppIds(); + int[] getPowerSaveWhitelistUserAppIds(); int[] getPowerSaveTempWhitelistAppIds(); diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java index fab5b5fd6933..606f0df0dfda 100644 --- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java @@ -109,6 +109,12 @@ public class AppStateTrackerImpl implements AppStateTracker { final SparseBooleanArray mActiveUids = new SparseBooleanArray(); /** + * System exemption list in the device idle controller. + */ + @GuardedBy("mLock") + private int[] mPowerExemptSystemAppIds = new int[0]; + + /** * System except-idle + user exemption list in the device idle controller. */ @GuardedBy("mLock") @@ -1075,6 +1081,7 @@ public class AppStateTrackerImpl implements AppStateTracker { * Called by device idle controller to update the power save exemption lists. */ public void setPowerSaveExemptionListAppIds( + int[] powerSaveExemptionListSystemAppIdArray, int[] powerSaveExemptionListExceptIdleAppIdArray, int[] powerSaveExemptionListUserAppIdArray, int[] tempExemptionListAppIdArray) { @@ -1082,6 +1089,7 @@ public class AppStateTrackerImpl implements AppStateTracker { final int[] previousExemptionList = mPowerExemptAllAppIds; final int[] previousTempExemptionList = mTempExemptAppIds; + mPowerExemptSystemAppIds = powerSaveExemptionListSystemAppIdArray; mPowerExemptAllAppIds = powerSaveExemptionListExceptIdleAppIdArray; mTempExemptAppIds = tempExemptionListAppIdArray; mPowerExemptUserAppIds = powerSaveExemptionListUserAppIdArray; @@ -1302,6 +1310,18 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** + * @return whether or not a UID is in either the user defined power-save exemption list or the + system full exemption list (not including except-idle) + */ + public boolean isUidPowerSaveIdleExempt(int uid) { + final int appId = UserHandle.getAppId(uid); + synchronized (mLock) { + return ArrayUtils.contains(mPowerExemptUserAppIds, appId) + || ArrayUtils.contains(mPowerExemptSystemAppIds, appId); + } + } + + /** * @return whether a UID is in the temp power-save exemption list or not. * * Note clients normally shouldn't need to access it. It's only for dumpsys. @@ -1338,6 +1358,9 @@ public class AppStateTrackerImpl implements AppStateTracker { pw.print("Active uids: "); dumpUids(pw, mActiveUids); + pw.print("System exemption list appids: "); + pw.println(Arrays.toString(mPowerExemptSystemAppIds)); + pw.print("Except-idle + user exemption list appids: "); pw.println(Arrays.toString(mPowerExemptAllAppIds)); @@ -1415,6 +1438,10 @@ public class AppStateTrackerImpl implements AppStateTracker { } } + for (int appId : mPowerExemptSystemAppIds) { + proto.write(AppStateTrackerProto.POWER_SAVE_SYSTEM_EXEMPT_APP_IDS, appId); + } + for (int appId : mPowerExemptAllAppIds) { proto.write(AppStateTrackerProto.POWER_SAVE_EXEMPT_APP_IDS, appId); } diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 40d1b4c9b267..40a51bd3470a 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -563,6 +563,12 @@ public class DeviceIdleController extends SystemService private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray(); /** + * Current system app IDs that are in the complete power save white list. This array can + * be shared with others because it will not be modified once set. + */ + private int[] mPowerSaveWhitelistSystemAppIdArray = new int[0]; + + /** * App IDs that have been white-listed to opt out of power save restrictions, except * for device idle modes. */ @@ -2089,6 +2095,11 @@ public class DeviceIdleController extends SystemService return DeviceIdleController.this.isAppOnWhitelistInternal(appid); } + @Override + public int[] getPowerSaveWhitelistSystemAppIds() { + return DeviceIdleController.this.getPowerSaveSystemWhitelistAppIds(); + } + /** * Returns the array of app ids whitelisted by user. Take care not to * modify this, as it is a reference to the original copy. But the reference @@ -2271,6 +2282,12 @@ public class DeviceIdleController extends SystemService } } + int[] getPowerSaveSystemWhitelistAppIds() { + synchronized (this) { + return mPowerSaveWhitelistSystemAppIdArray; + } + } + int[] getPowerSaveWhitelistUserAppIds() { synchronized (this) { return mPowerSaveWhitelistUserAppIdArray; @@ -2281,6 +2298,16 @@ public class DeviceIdleController extends SystemService return new File(Environment.getDataDirectory(), "system"); } + /** Returns the keys of a SparseBooleanArray, paying no attention to its values. */ + private static int[] keysToIntArray(final SparseBooleanArray sparseArray) { + final int size = sparseArray.size(); + final int[] array = new int[size]; + for (int i = 0; i < size; i++) { + array[i] = sparseArray.keyAt(i); + } + return array; + } + @Override public void onStart() { final PackageManager pm = getContext().getPackageManager(); @@ -2317,6 +2344,7 @@ public class DeviceIdleController extends SystemService } catch (PackageManager.NameNotFoundException e) { } } + mPowerSaveWhitelistSystemAppIdArray = keysToIntArray(mPowerSaveWhitelistSystemAppIds); mConstants = mInjector.getConstants(this); @@ -4222,6 +4250,7 @@ public class DeviceIdleController extends SystemService private void passWhiteListsToForceAppStandbyTrackerLocked() { mAppStateTracker.setPowerSaveExemptionListAppIds( + mPowerSaveWhitelistSystemAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray, mPowerSaveWhitelistUserAppIdArray, mTempWhitelistAppIdArray); diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 37ce0d29d0e1..a65e86d888de 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -2861,7 +2861,7 @@ public class AlarmManagerService extends SystemService { } else if (workSource == null && (UserHandle.isCore(callingUid) || UserHandle.isSameApp(callingUid, mSystemUiUid) || ((mAppStateTracker != null) - && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) { + && mAppStateTracker.isUidPowerSaveIdleExempt(callingUid)))) { flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE); } 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 abbe177c5d49..01f0b30cc48a 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 @@ -74,6 +74,7 @@ public final class DeviceIdleJobsController extends StateController { * True when in device idle mode, so we don't want to schedule any jobs. */ private boolean mDeviceIdleMode; + private int[] mPowerSaveWhitelistSystemAppIds; private int[] mDeviceIdleWhitelistAppIds; private int[] mPowerSaveTempWhitelistAppIds; @@ -133,6 +134,8 @@ public final class DeviceIdleJobsController extends StateController { mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds(); + mPowerSaveWhitelistSystemAppIds = + mLocalDeviceIdleController.getPowerSaveWhitelistSystemAppIds(); mPowerSaveTempWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds(); mDeviceIdleUpdateFunctor = new DeviceIdleUpdateFunctor(); @@ -196,8 +199,9 @@ public final class DeviceIdleJobsController extends StateController { * Checks if the given job's scheduling app id exists in the device idle user whitelist. */ boolean isWhitelistedLocked(JobStatus job) { - return Arrays.binarySearch(mDeviceIdleWhitelistAppIds, - UserHandle.getAppId(job.getSourceUid())) >= 0; + final int appId = UserHandle.getAppId(job.getSourceUid()); + return Arrays.binarySearch(mDeviceIdleWhitelistAppIds, appId) >= 0 + || Arrays.binarySearch(mPowerSaveWhitelistSystemAppIds, appId) >= 0; } /** diff --git a/core/proto/android/server/appstatetracker.proto b/core/proto/android/server/appstatetracker.proto index f5583d4f476f..0d0fb097d963 100644 --- a/core/proto/android/server/appstatetracker.proto +++ b/core/proto/android/server/appstatetracker.proto @@ -25,7 +25,7 @@ option java_multiple_files = true; // Dump from com.android.server.AppStateTracker. // -// Next ID: 14 +// Next ID: 15 message AppStateTrackerProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; @@ -41,6 +41,9 @@ message AppStateTrackerProto { // UIDs currently in the foreground. repeated int32 foreground_uids = 11; + // App ids that are in power-save system exemption list. + repeated int32 power_save_system_exempt_app_ids = 14; + // App ids that are in power-save exemption list. repeated int32 power_save_exempt_app_ids = 3; |