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

Commit 3bd5e1d7 authored by Kweku Adams's avatar Kweku Adams Committed by Automerger Merge Worker
Browse files

Merge "Add charging parole notification for network changes." into rvc-dev am: cdb03964

Change-Id: I2ca8f2928367fe0be27cbb24014f2cc51e4ae5e8
parents 283bb292 cdb03964
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,14 @@ public interface AppStandbyInternal {
        public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId,
        public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId,
                boolean idle, int bucket, int reason);
                boolean idle, int bucket, int reason);


        /**
         * Callback to inform listeners that the parole state has changed. This means apps are
         * allowed to do work even if they're idle or in a low bucket.
         */
        public void onParoleStateChanged(boolean isParoleOn) {
            // No-op by default
        }

        /**
        /**
         * Optional callback to inform the listener that the app has transitioned into
         * Optional callback to inform the listener that the app has transitioned into
         * an active state due to user interaction.
         * an active state due to user interaction.
@@ -92,6 +100,11 @@ public interface AppStandbyInternal {
    boolean isAppIdleFiltered(String packageName, int appId, int userId,
    boolean isAppIdleFiltered(String packageName, int appId, int userId,
            long elapsedRealtime);
            long elapsedRealtime);


    /**
     * @return true if currently app idle parole mode is on.
     */
    boolean isInParole();

    int[] getIdleUidsForUser(int userId);
    int[] getIdleUidsForUser(int userId);


    void setAppIdleAsync(String packageName, boolean idle, int userId);
    void setAppIdleAsync(String packageName, boolean idle, int userId);
+38 −3
Original line number Original line Diff line number Diff line
@@ -214,8 +214,7 @@ public class AppStandbyController implements AppStandbyInternal {
    private AppIdleHistory mAppIdleHistory;
    private AppIdleHistory mAppIdleHistory;


    @GuardedBy("mPackageAccessListeners")
    @GuardedBy("mPackageAccessListeners")
    private ArrayList<AppIdleStateChangeListener>
    private final ArrayList<AppIdleStateChangeListener> mPackageAccessListeners = new ArrayList<>();
            mPackageAccessListeners = new ArrayList<>();


    /** Whether we've queried the list of carrier privileged apps. */
    /** Whether we've queried the list of carrier privileged apps. */
    @GuardedBy("mAppIdleLock")
    @GuardedBy("mAppIdleLock")
@@ -235,6 +234,7 @@ public class AppStandbyController implements AppStandbyInternal {
    static final int MSG_FORCE_IDLE_STATE = 4;
    static final int MSG_FORCE_IDLE_STATE = 4;
    static final int MSG_CHECK_IDLE_STATES = 5;
    static final int MSG_CHECK_IDLE_STATES = 5;
    static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
    static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
    static final int MSG_PAROLE_STATE_CHANGED = 9;
    static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
    static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
    /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
    /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
    static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
    static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
@@ -390,7 +390,16 @@ public class AppStandbyController implements AppStandbyInternal {


    @VisibleForTesting
    @VisibleForTesting
    void setAppIdleEnabled(boolean enabled) {
    void setAppIdleEnabled(boolean enabled) {
        synchronized (mAppIdleLock) {
            if (mAppIdleEnabled != enabled) {
                final boolean oldParoleState = isInParole();
                mAppIdleEnabled = enabled;
                mAppIdleEnabled = enabled;
                if (isInParole() != oldParoleState) {
                    postParoleStateChanged();
                }
            }
        }

    }
    }


    @Override
    @Override
@@ -563,10 +572,22 @@ public class AppStandbyController implements AppStandbyInternal {
            if (mIsCharging != isCharging) {
            if (mIsCharging != isCharging) {
                if (DEBUG) Slog.d(TAG, "Setting mIsCharging to " + isCharging);
                if (DEBUG) Slog.d(TAG, "Setting mIsCharging to " + isCharging);
                mIsCharging = isCharging;
                mIsCharging = isCharging;
                postParoleStateChanged();
            }
            }
        }
        }
    }
    }


    @Override
    public boolean isInParole() {
        return !mAppIdleEnabled || mIsCharging;
    }

    private void postParoleStateChanged() {
        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
        mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
        mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
    }

    @Override
    @Override
    public void postCheckIdleStates(int userId) {
    public void postCheckIdleStates(int userId) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
@@ -1502,6 +1523,15 @@ public class AppStandbyController implements AppStandbyInternal {
        }
        }
    }
    }


    private void informParoleStateChanged() {
        final boolean paroled = isInParole();
        synchronized (mPackageAccessListeners) {
            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
                listener.onParoleStateChanged(paroled);
            }
        }
    }

    @Override
    @Override
    public void flushToDisk(int userId) {
    public void flushToDisk(int userId) {
        synchronized (mAppIdleLock) {
        synchronized (mAppIdleLock) {
@@ -1920,6 +1950,11 @@ public class AppStandbyController implements AppStandbyInternal {
                    args.recycle();
                    args.recycle();
                    break;
                    break;


                case MSG_PAROLE_STATE_CHANGED:
                    if (DEBUG) Slog.d(TAG, "Parole state: " + isInParole());
                    informParoleStateChanged();
                    break;

                case MSG_CHECK_PACKAGE_IDLE_STATE:
                case MSG_CHECK_PACKAGE_IDLE_STATE:
                    checkAndUpdateStandbyState((String) msg.obj, msg.arg1, msg.arg2,
                    checkAndUpdateStandbyState((String) msg.obj, msg.arg1, msg.arg2,
                            mInjector.elapsedRealtime());
                            mInjector.elapsedRealtime());
+52 −7
Original line number Original line Diff line number Diff line
@@ -799,7 +799,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                        writePolicyAL();
                        writePolicyAL();
                    }
                    }


                    enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, true);
                    setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
                    setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
                    updateRulesForGlobalChangeAL(false);
                    updateRulesForGlobalChangeAL(false);
                    updateNotificationsNL();
                    updateNotificationsNL();
@@ -871,6 +870,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
                    new NetworkRequest.Builder().build(), mNetworkCallback);
                    new NetworkRequest.Builder().build(), mNetworkCallback);


            mAppStandby.addListener(new NetPolicyAppIdleStateChangeListener());
            mAppStandby.addListener(new NetPolicyAppIdleStateChangeListener());
            synchronized (mUidRulesFirstLock) {
                updateRulesForAppIdleParoleUL();
            }


            // Listen for subscriber changes
            // Listen for subscriber changes
            mContext.getSystemService(SubscriptionManager.class).addOnSubscriptionsChangedListener(
            mContext.getSystemService(SubscriptionManager.class).addOnSubscriptionsChangedListener(
@@ -3892,6 +3894,39 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
        }
        }
    }
    }


    /**
     * Toggle the firewall standby chain and inform listeners if the uid rules have effectively
     * changed.
     */
    @GuardedBy("mUidRulesFirstLock")
    private void updateRulesForAppIdleParoleUL() {
        final boolean paroled = mAppStandby.isInParole();
        final boolean enableChain = !paroled;
        enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, enableChain);

        int ruleCount = mUidFirewallStandbyRules.size();
        for (int i = 0; i < ruleCount; i++) {
            final int uid = mUidFirewallStandbyRules.keyAt(i);
            int oldRules = mUidRules.get(uid);
            if (enableChain) {
                // Chain wasn't enabled before and the other power-related
                // chains are whitelists, so we can clear the
                // MASK_ALL_NETWORKS part of the rules and re-inform listeners if
                // the effective rules result in blocking network access.
                oldRules &= MASK_METERED_NETWORKS;
            } else {
                // Skip if it had no restrictions to begin with
                if ((oldRules & MASK_ALL_NETWORKS) == 0) continue;
            }
            final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules, paroled);
            if (newUidRules == RULE_NONE) {
                mUidRules.delete(uid);
            } else {
                mUidRules.put(uid, newUidRules);
            }
        }
    }

    /**
    /**
     * Update rules that might be changed by {@link #mRestrictBackground},
     * Update rules that might be changed by {@link #mRestrictBackground},
     * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
     * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
@@ -4347,7 +4382,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    private void updateRulesForPowerRestrictionsUL(int uid) {
    private void updateRulesForPowerRestrictionsUL(int uid) {
        final int oldUidRules = mUidRules.get(uid, RULE_NONE);
        final int oldUidRules = mUidRules.get(uid, RULE_NONE);


        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules);
        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules, false);


        if (newUidRules == RULE_NONE) {
        if (newUidRules == RULE_NONE) {
            mUidRules.delete(uid);
            mUidRules.delete(uid);
@@ -4361,28 +4396,30 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     *
     *
     * @param uid the uid of the app to update rules for
     * @param uid the uid of the app to update rules for
     * @param oldUidRules the current rules for the uid, in order to determine if there's a change
     * @param oldUidRules the current rules for the uid, in order to determine if there's a change
     * @param paroled whether to ignore idle state of apps and only look at other restrictions
     *
     *
     * @return the new computed rules for the uid
     * @return the new computed rules for the uid
     */
     */
    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules) {
    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean paroled) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
                    "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules);
                    "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules + "/"
                            + (paroled ? "P" : "-"));
        }
        }
        try {
        try {
            return updateRulesForPowerRestrictionsULInner(uid, oldUidRules);
            return updateRulesForPowerRestrictionsULInner(uid, oldUidRules, paroled);
        } finally {
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
        }
    }
    }


    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules) {
    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules, boolean paroled) {
        if (!isUidValidForBlacklistRules(uid)) {
        if (!isUidValidForBlacklistRules(uid)) {
            if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
            if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
            return RULE_NONE;
            return RULE_NONE;
        }
        }


        final boolean isIdle = isUidIdle(uid);
        final boolean isIdle = !paroled && isUidIdle(uid);
        final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
        final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
        final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
        final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);


@@ -4452,6 +4489,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
            } catch (NameNotFoundException nnfe) {
            } catch (NameNotFoundException nnfe) {
            }
            }
        }
        }

        @Override
        public void onParoleStateChanged(boolean isParoleOn) {
            synchronized (mUidRulesFirstLock) {
                mLogger.paroleStateChanged(isParoleOn);
                updateRulesForAppIdleParoleUL();
            }
        }
    }
    }


    private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
    private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
+64 −0
Original line number Original line Diff line number Diff line
@@ -366,29 +366,87 @@ public class AppStandbyControllerTests {
                        mInjector.mElapsedRealtime, false));
                        mInjector.mElapsedRealtime, false));
    }
    }


    private static class TestParoleListener extends AppIdleStateChangeListener {
        private boolean mIsParoleOn = false;
        private CountDownLatch mLatch;
        private boolean mIsExpecting = false;
        private boolean mExpectedParoleState;

        boolean getParoleState() {
            synchronized (this) {
                return mIsParoleOn;
            }
        }

        void rearmLatch(boolean expectedParoleState) {
            synchronized (this) {
                mLatch = new CountDownLatch(1);
                mIsExpecting = true;
                mExpectedParoleState = expectedParoleState;
            }
        }

        void awaitOnLatch(long time) throws Exception {
            mLatch.await(time, TimeUnit.MILLISECONDS);
        }

        @Override
        public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
                int bucket, int reason) {
        }

        @Override
        public void onParoleStateChanged(boolean isParoleOn) {
            synchronized (this) {
                // Only record information if it is being looked for
                if (mLatch != null && mLatch.getCount() > 0) {
                    mIsParoleOn = isParoleOn;
                    if (mIsExpecting && isParoleOn == mExpectedParoleState) {
                        mLatch.countDown();
                    }
                }
            }
        }
    }

    @Test
    @Test
    public void testIsAppIdle_Charging() throws Exception {
    public void testIsAppIdle_Charging() throws Exception {
        TestParoleListener paroleListener = new TestParoleListener();
        mController.addListener(paroleListener);

        setChargingState(mController, false);
        setChargingState(mController, false);
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
                REASON_MAIN_FORCED_BY_SYSTEM);
                REASON_MAIN_FORCED_BY_SYSTEM);
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertFalse(mController.isInParole());


        paroleListener.rearmLatch(true);
        setChargingState(mController, true);
        setChargingState(mController, true);
        paroleListener.awaitOnLatch(2000);
        assertTrue(paroleListener.getParoleState());
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertTrue(mController.isInParole());


        paroleListener.rearmLatch(false);
        setChargingState(mController, false);
        setChargingState(mController, false);
        paroleListener.awaitOnLatch(2000);
        assertFalse(paroleListener.getParoleState());
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertFalse(mController.isInParole());
    }
    }


    @Test
    @Test
    public void testIsAppIdle_Enabled() throws Exception {
    public void testIsAppIdle_Enabled() throws Exception {
        setChargingState(mController, false);
        setChargingState(mController, false);
        TestParoleListener paroleListener = new TestParoleListener();
        mController.addListener(paroleListener);

        setAppIdleEnabled(mController, true);
        setAppIdleEnabled(mController, true);
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
                REASON_MAIN_FORCED_BY_SYSTEM);
                REASON_MAIN_FORCED_BY_SYSTEM);
@@ -396,11 +454,17 @@ public class AppStandbyControllerTests {
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));


        paroleListener.rearmLatch(false);
        setAppIdleEnabled(mController, false);
        setAppIdleEnabled(mController, false);
        paroleListener.awaitOnLatch(2000);
        assertTrue(paroleListener.mIsParoleOn);
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));


        paroleListener.rearmLatch(true);
        setAppIdleEnabled(mController, true);
        setAppIdleEnabled(mController, true);
        paroleListener.awaitOnLatch(2000);
        assertFalse(paroleListener.getParoleState());
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, false));