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

Commit a2c159fe authored by Xiaohui Chen's avatar Xiaohui Chen Committed by Android (Google) Code Review
Browse files

Merge "system_server: optimize app idle parole state change" into mnc-dev

parents a1ee09c8 8dca36dc
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -76,6 +76,12 @@ public abstract class UsageStatsManagerInternal {
     */
    public abstract boolean isAppIdle(String packageName, int userId);

    /**
     * @return True if currently app idle parole mode is on.  This means all idle apps are allow to
     * run for a short period of time.
     */
    public abstract boolean isAppIdleParoleOn();

    /**
     * Sets up a listener for changes to packages being accessed.
     * @param listener A listener within the system process.
@@ -90,8 +96,9 @@ public abstract class UsageStatsManagerInternal {
    public abstract void removeAppIdleStateChangeListener(
            AppIdleStateChangeListener listener);

    public interface AppIdleStateChangeListener {
        void onAppIdleStateChanged(String packageName, int userId, boolean idle);
    public static abstract class AppIdleStateChangeListener {
        public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle);
        public abstract void onParoleStateChanged(boolean isParoleOn);
    }

}
+80 −63
Original line number Diff line number Diff line
@@ -214,9 +214,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
     */
    @GuardedBy("mQuotaLock")
    private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();

    private boolean mStandbyChainEnabled = false;
    private boolean mDozableChainEnabled = false;
    /** Set of states for the child firewall chains. True if the chain is active. */
    @GuardedBy("mQuotaLock")
    final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();

    private Object mIdleTimerLock = new Object();
    /** Set of interfaces with active idle timers. */
@@ -307,9 +307,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    }

    public void systemReady() {
        // init firewall states
        mDozableChainEnabled = false;
        mStandbyChainEnabled = true;
        prepareNativeDaemon();
        if (DBG) Slog.d(TAG, "Prepared");
    }
@@ -611,7 +608,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                            uidFirewallRules.valueAt(i));
                }
            }
            if (mStandbyChainEnabled) {
            if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)) {
                setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true);
            }

@@ -625,7 +622,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                            uidFirewallRules.valueAt(i));
                }
            }
            if (mDozableChainEnabled) {
            if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
                setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
            }
        }
@@ -2013,17 +2010,23 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    @Override
    public void setFirewallChainEnabled(int chain, boolean enable) {
        enforceSystemUid();
        synchronized (mQuotaLock) {
            if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
                    mFirewallChainStates.get(chain) == enable) {
                // All is the same, nothing to do.
                return;
            }
            mFirewallChainStates.put(chain, enable);

            final String operation = enable ? "enable_chain" : "disable_chain";
            try {
                String chainName;
                switch(chain) {
                    case FIREWALL_CHAIN_STANDBY:
                        chainName = FIREWALL_CHAIN_NAME_STANDBY;
                    mStandbyChainEnabled = enable;
                        break;
                    case FIREWALL_CHAIN_DOZABLE:
                        chainName = FIREWALL_CHAIN_NAME_DOZABLE;
                    mDozableChainEnabled = enable;
                        break;
                    default:
                        throw new IllegalArgumentException("Bad child chain: " + chain);
@@ -2033,6 +2036,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                throw e.rethrowAsParcelableException();
            }
        }
    }

    private int getFirewallType(int chain) {
        switch (chain) {
@@ -2048,6 +2052,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
    @Override
    public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
        enforceSystemUid();
        synchronized (mQuotaLock) {
            SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
            SparseIntArray newRules = new SparseIntArray();
            // apply new set of rules
@@ -2071,6 +2076,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT);
            }
        }
    }

    @Override
    public void setFirewallUidRule(int chain, int uid, int rule) {
@@ -2094,6 +2100,26 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            }

            try {
                String ruleName = getFirewallRuleName(chain, rule);
                String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);

                if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
                    uidFirewallRules.delete(uid);
                } else {
                    uidFirewallRules.put(uid, rule);
                }

                if (!ruleName.equals(oldRuleName)) {
                    mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
                            ruleName);
                }
            } catch (NativeDaemonConnectorException e) {
                throw e.rethrowAsParcelableException();
            }
        }
    }

    private @NonNull String getFirewallRuleName(int chain, int rule) {
        String ruleName;
        if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
            if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
@@ -2108,18 +2134,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                ruleName = "allow";
            }
        }

                if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
                    uidFirewallRules.delete(uid);
                } else {
                    uidFirewallRules.put(uid, rule);
                }
                mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
                        ruleName);
            } catch (NativeDaemonConnectorException e) {
                throw e.rethrowAsParcelableException();
            }
        }
        return ruleName;
    }

    private @NonNull SparseIntArray getUidFirewallRules(int chain) {
@@ -2272,7 +2287,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            pw.println("]");
        }

        pw.println("UID firewall standby chain enabled: " + mStandbyChainEnabled);
        pw.println("UID firewall standby chain enabled: " +
                mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
        synchronized (mUidFirewallStandbyRules) {
            pw.print("UID firewall standby rule: [");
            final int size = mUidFirewallStandbyRules.size();
@@ -2285,7 +2301,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
            pw.println("]");
        }

        pw.println("UID firewall dozable chain enabled: " + mDozableChainEnabled);
        pw.println("UID firewall dozable chain enabled: " +
                mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
        synchronized (mUidFirewallDozableRules) {
            pw.print("UID firewall dozable rule: [");
            final int size = mUidFirewallDozableRules.size();
+15 −36
Original line number Diff line number Diff line
@@ -18,11 +18,6 @@ package com.android.server.content;

import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.UserHandle;

import com.android.server.LocalServices;
@@ -31,53 +26,32 @@ import com.android.server.LocalServices;
 * Helper to listen for app idle and charging status changes and restart backed off
 * sync operations.
 */
class AppIdleMonitor implements AppIdleStateChangeListener {
class AppIdleMonitor extends AppIdleStateChangeListener {

    private final SyncManager mSyncManager;
    private final UsageStatsManagerInternal mUsageStats;
    final BatteryManager mBatteryManager;
    /** Is the device currently plugged into power. */
    private boolean mPluggedIn;
    private boolean mAppIdleParoleOn;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            onPluggedIn(mBatteryManager.isCharging());
        }
    };

    AppIdleMonitor(SyncManager syncManager, Context context) {
    AppIdleMonitor(SyncManager syncManager) {
        mSyncManager = syncManager;
        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
        mUsageStats.addAppIdleStateChangeListener(this);
        mBatteryManager = context.getSystemService(BatteryManager.class);
        mPluggedIn = isPowered();
        registerReceivers(context);
    }
        mAppIdleParoleOn = mUsageStats.isAppIdleParoleOn();

    private void registerReceivers(Context context) {
        // Monitor battery charging state
        IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
        filter.addAction(BatteryManager.ACTION_DISCHARGING);
        context.registerReceiver(mReceiver, filter);
    }

    private boolean isPowered() {
        return mBatteryManager.isCharging();
        mUsageStats.addAppIdleStateChangeListener(this);
    }

    void onPluggedIn(boolean pluggedIn) {
        if (mPluggedIn == pluggedIn) {
    void setAppIdleParoleOn(boolean appIdleParoleOn) {
        if (mAppIdleParoleOn == appIdleParoleOn) {
            return;
        }
        mPluggedIn = pluggedIn;
        if (mPluggedIn) {
        mAppIdleParoleOn = appIdleParoleOn;
        if (mAppIdleParoleOn) {
            mSyncManager.onAppNotIdle(null, UserHandle.USER_ALL);
        }
    }

    boolean isAppIdle(String packageName, int userId) {
        return !mPluggedIn && mUsageStats.isAppIdle(packageName, userId);
        return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, userId);
    }

    @Override
@@ -86,4 +60,9 @@ class AppIdleMonitor implements AppIdleStateChangeListener {
        if (idle) return;
        mSyncManager.onAppNotIdle(packageName, userId);
    }

    @Override
    public void onParoleStateChanged(boolean isParoleOn) {
        setAppIdleParoleOn(isParoleOn);
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.content;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AppGlobals;
@@ -461,7 +462,7 @@ public class SyncManager {
        mSyncAlarmIntent = PendingIntent.getBroadcast(
                mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0);

        mAppIdleMonitor = new AppIdleMonitor(this, mContext);
        mAppIdleMonitor = new AppIdleMonitor(this);

        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
@@ -1271,7 +1272,7 @@ public class SyncManager {
     * @param userId The user for which the package has become active. Can be USER_ALL if
     * the device just plugged in.
     */
    void onAppNotIdle(String packageName, int userId) {
    void onAppNotIdle(@Nullable String packageName, int userId) {
        synchronized (mSyncQueue) {
            // For all sync operations in sync queue, if marked as idle, compare with package name
            // and unmark. And clear backoff for the operation.
+48 −61
Original line number Diff line number Diff line
@@ -17,12 +17,7 @@
package com.android.server.job.controllers;

import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.util.Slog;

import com.android.server.LocalServices;
@@ -38,8 +33,7 @@ import java.util.ArrayList;
 * for a certain amount of time (maybe hours or days) are considered idle. When the app comes
 * out of idle state, it will be allowed to run scheduled jobs.
 */
public class AppIdleController extends StateController
        implements UsageStatsManagerInternal.AppIdleStateChangeListener {
public class AppIdleController extends StateController {

    private static final String LOG_TAG = "AppIdleController";
    private static final boolean DEBUG = false;
@@ -49,14 +43,7 @@ public class AppIdleController extends StateController
    private static volatile AppIdleController sController;
    final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
    private final UsageStatsManagerInternal mUsageStatsInternal;
    private final BatteryManager mBatteryManager;
    private boolean mPluggedIn;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override public void onReceive(Context context, Intent intent) {
            onPluggedIn(mBatteryManager.isCharging());
        }
    };
    boolean mAppIdleParoleOn;

    public static AppIdleController get(JobSchedulerService service) {
        synchronized (sCreationLock) {
@@ -70,17 +57,8 @@ public class AppIdleController extends StateController
    private AppIdleController(StateChangedListener stateChangedListener, Context context) {
        super(stateChangedListener, context);
        mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
        mBatteryManager = context.getSystemService(BatteryManager.class);
        mPluggedIn = mBatteryManager.isCharging();
        mUsageStatsInternal.addAppIdleStateChangeListener(this);
        registerReceivers();
    }

    private void registerReceivers() {
        // Monitor battery charging state
        IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
        filter.addAction(BatteryManager.ACTION_DISCHARGING);
        mContext.registerReceiver(mReceiver, filter);
        mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
        mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
    }

    @Override
@@ -88,7 +66,7 @@ public class AppIdleController extends StateController
        synchronized (mTrackedTasks) {
            mTrackedTasks.add(jobStatus);
            String packageName = jobStatus.job.getService().getPackageName();
            final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
            final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
                    jobStatus.getUserId());
            if (DEBUG) {
                Slog.d(LOG_TAG, "Start tracking, setting idle state of "
@@ -108,7 +86,7 @@ public class AppIdleController extends StateController
    @Override
    public void dumpControllerState(PrintWriter pw) {
        pw.println("AppIdle");
        pw.println("Plugged In: " + mPluggedIn);
        pw.println("Parole On: " + mAppIdleParoleOn);
        synchronized (mTrackedTasks) {
            for (JobStatus task : mTrackedTasks) {
                pw.print(task.job.getService().getPackageName());
@@ -119,57 +97,66 @@ public class AppIdleController extends StateController
        }
    }

    @Override
    public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
    void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
        // Flag if any app's idle state has changed
        boolean changed = false;
        synchronized (mTrackedTasks) {
            // If currently plugged in, we don't care about app idle state
            if (mPluggedIn) {
            if (mAppIdleParoleOn == isAppIdleParoleOn) {
                return;
            }
            mAppIdleParoleOn = isAppIdleParoleOn;
            for (JobStatus task : mTrackedTasks) {
                if (task.job.getService().getPackageName().equals(packageName)
                        && task.getUserId() == userId) {
                    if (task.appNotIdleConstraintSatisfied.get() != !idle) {
                String packageName = task.job.getService().getPackageName();
                final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
                        task.getUserId());
                if (DEBUG) {
                            Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
                                    + packageName + " to " + idle);
                    Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
                }
                        task.appNotIdleConstraintSatisfied.set(!idle);
                if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
                    task.appNotIdleConstraintSatisfied.set(!appIdle);
                    changed = true;
                }
            }
        }
        }
        if (changed) {
            mStateChangedListener.onControllerStateChanged();
        }
    }

    void onPluggedIn(boolean pluggedIn) {
        // Flag if any app's idle state has changed
    private class AppIdleStateChangeListener
            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
        @Override
        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
            boolean changed = false;
            synchronized (mTrackedTasks) {
            if (mPluggedIn == pluggedIn) {
                if (mAppIdleParoleOn) {
                    return;
                }
            mPluggedIn = pluggedIn;
                for (JobStatus task : mTrackedTasks) {
                String packageName = task.job.getService().getPackageName();
                final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
                        task.getUserId());
                    if (task.job.getService().getPackageName().equals(packageName)
                            && task.getUserId() == userId) {
                        if (task.appNotIdleConstraintSatisfied.get() != !idle) {
                            if (DEBUG) {
                    Slog.d(LOG_TAG, "Plugged in " + pluggedIn + ", setting idle state of "
                            + packageName + " to " + appIdle);
                                Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
                                        + packageName + " to " + idle);
                            }
                if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
                    task.appNotIdleConstraintSatisfied.set(!appIdle);
                            task.appNotIdleConstraintSatisfied.set(!idle);
                            changed = true;
                        }
                    }
                }
            }
            if (changed) {
                mStateChangedListener.onControllerStateChanged();
            }
        }

        @Override
        public void onParoleStateChanged(boolean isParoleOn) {
            if (DEBUG) {
                Slog.d(LOG_TAG, "Parole on: " + isParoleOn);
            }
            setAppIdleParoleOn(isParoleOn);
        }
    }
}
Loading