Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d36faad3 authored by Tommy Webb's avatar Tommy Webb Committed by Michael Bestas
Browse files

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
parent f0a3206c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -73,6 +73,8 @@ public interface DeviceIdleInternal {

    boolean isAppOnWhitelist(int appid);

    int[] getPowerSaveWhitelistSystemAppIds();

    int[] getPowerSaveWhitelistUserAppIds();

    int[] getPowerSaveTempWhitelistAppIds();
+27 −0
Original line number Diff line number Diff line
@@ -108,6 +108,12 @@ public class AppStateTrackerImpl implements AppStateTracker {
    @GuardedBy("mLock")
    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.
     */
@@ -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;
@@ -1301,6 +1309,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.
     *
@@ -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);
            }
+29 −0
Original line number Diff line number Diff line
@@ -562,6 +562,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);
+1 −1
Original line number Diff line number Diff line
@@ -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);
            }
+6 −2
Original line number Diff line number Diff line
@@ -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;
    }

    /**
Loading