diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java index 8a31390dbf260..9113426da1297 100644 --- a/core/java/android/app/usage/UsageStatsManagerInternal.java +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java @@ -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); } } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index baa55e721a287..7afb192794f08 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -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,24 +2010,31 @@ public class NetworkManagementService extends INetworkManagementService.Stub @Override public void setFirewallChainEnabled(int chain, boolean enable) { enforceSystemUid(); - 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); + 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; + break; + case FIREWALL_CHAIN_DOZABLE: + chainName = FIREWALL_CHAIN_NAME_DOZABLE; + break; + default: + throw new IllegalArgumentException("Bad child chain: " + chain); + } + mConnector.execute("firewall", operation, chainName); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); } - mConnector.execute("firewall", operation, chainName); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); } } @@ -2048,27 +2052,29 @@ public class NetworkManagementService extends INetworkManagementService.Stub @Override public void setFirewallUidRules(int chain, int[] uids, int[] rules) { enforceSystemUid(); - SparseIntArray uidFirewallRules = getUidFirewallRules(chain); - SparseIntArray newRules = new SparseIntArray(); - // apply new set of rules - for (int index = uids.length - 1; index >= 0; --index) { - int uid = uids[index]; - int rule = rules[index]; - setFirewallUidRule(chain, uid, rule); - newRules.put(uid, rule); - } - // collect the rules to remove. - SparseIntArray rulesToRemove = new SparseIntArray(); - for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { - int uid = uidFirewallRules.keyAt(index); - if (newRules.indexOfKey(uid) < 0) { - rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); + synchronized (mQuotaLock) { + SparseIntArray uidFirewallRules = getUidFirewallRules(chain); + SparseIntArray newRules = new SparseIntArray(); + // apply new set of rules + for (int index = uids.length - 1; index >= 0; --index) { + int uid = uids[index]; + int rule = rules[index]; + setFirewallUidRule(chain, uid, rule); + newRules.put(uid, rule); + } + // collect the rules to remove. + SparseIntArray rulesToRemove = new SparseIntArray(); + for (int index = uidFirewallRules.size() - 1; index >= 0; --index) { + int uid = uidFirewallRules.keyAt(index); + if (newRules.indexOfKey(uid) < 0) { + rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT); + } + } + // remove dead rules + for (int index = rulesToRemove.size() - 1; index >= 0; --index) { + int uid = rulesToRemove.keyAt(index); + setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT); } - } - // remove dead rules - for (int index = rulesToRemove.size() - 1; index >= 0; --index) { - int uid = rulesToRemove.keyAt(index); - setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT); } } @@ -2094,34 +2100,43 @@ public class NetworkManagementService extends INetworkManagementService.Stub } try { - String ruleName; - if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { - if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { - ruleName = "allow"; - } else { - ruleName = "deny"; - } - } else { // Blacklist mode - if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { - ruleName = "deny"; - } else { - ruleName = "allow"; - } - } + String ruleName = getFirewallRuleName(chain, rule); + String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule); if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { uidFirewallRules.delete(uid); } else { uidFirewallRules.put(uid, rule); } - mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid, - ruleName); + + 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) { + ruleName = "allow"; + } else { + ruleName = "deny"; + } + } else { // Blacklist mode + if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { + ruleName = "deny"; + } else { + ruleName = "allow"; + } + } + return ruleName; + } + private @NonNull SparseIntArray getUidFirewallRules(int chain) { switch (chain) { case FIREWALL_CHAIN_STANDBY: @@ -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(); diff --git a/services/core/java/com/android/server/content/AppIdleMonitor.java b/services/core/java/com/android/server/content/AppIdleMonitor.java index 9598de8e5c248..fe5c2da4c6d1b 100644 --- a/services/core/java/com/android/server/content/AppIdleMonitor.java +++ b/services/core/java/com/android/server/content/AppIdleMonitor.java @@ -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); + mAppIdleParoleOn = mUsageStats.isAppIdleParoleOn(); + mUsageStats.addAppIdleStateChangeListener(this); - mBatteryManager = context.getSystemService(BatteryManager.class); - mPluggedIn = isPowered(); - registerReceivers(context); } - 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(); - } - - 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); + } } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 7415b0ee624c3..658f6f858acc6 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -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. diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java index 98fb11b6aef26..02d4f40342443 100644 --- a/services/core/java/com/android/server/job/controllers/AppIdleController.java +++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java @@ -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 mTrackedTasks = new ArrayList(); 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,48 +97,20 @@ public class AppIdleController extends StateController } } - @Override - public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { - boolean changed = false; - synchronized (mTrackedTasks) { - // If currently plugged in, we don't care about app idle state - if (mPluggedIn) { - return; - } - for (JobStatus task : mTrackedTasks) { - if (task.job.getService().getPackageName().equals(packageName) - && task.getUserId() == userId) { - if (task.appNotIdleConstraintSatisfied.get() != !idle) { - if (DEBUG) { - Slog.d(LOG_TAG, "App Idle state changed, setting idle state of " - + packageName + " to " + idle); - } - task.appNotIdleConstraintSatisfied.set(!idle); - changed = true; - } - } - } - } - if (changed) { - mStateChangedListener.onControllerStateChanged(); - } - } - - void onPluggedIn(boolean pluggedIn) { + void setAppIdleParoleOn(boolean isAppIdleParoleOn) { // Flag if any app's idle state has changed boolean changed = false; synchronized (mTrackedTasks) { - if (mPluggedIn == pluggedIn) { + if (mAppIdleParoleOn == isAppIdleParoleOn) { return; } - mPluggedIn = pluggedIn; + mAppIdleParoleOn = isAppIdleParoleOn; for (JobStatus task : mTrackedTasks) { String packageName = task.job.getService().getPackageName(); - final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName, + final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName, task.getUserId()); if (DEBUG) { - Slog.d(LOG_TAG, "Plugged in " + pluggedIn + ", setting idle state of " - + packageName + " to " + appIdle); + Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle); } if (task.appNotIdleConstraintSatisfied.get() == appIdle) { task.appNotIdleConstraintSatisfied.set(!appIdle); @@ -172,4 +122,41 @@ public class AppIdleController extends StateController mStateChangedListener.onControllerStateChanged(); } } + + private class AppIdleStateChangeListener + extends UsageStatsManagerInternal.AppIdleStateChangeListener { + @Override + public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { + boolean changed = false; + synchronized (mTrackedTasks) { + if (mAppIdleParoleOn) { + return; + } + for (JobStatus task : mTrackedTasks) { + if (task.job.getService().getPackageName().equals(packageName) + && task.getUserId() == userId) { + if (task.appNotIdleConstraintSatisfied.get() != !idle) { + if (DEBUG) { + Slog.d(LOG_TAG, "App Idle state changed, setting idle state of " + + packageName + " to " + idle); + } + 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); + } + } } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index b0550d664b894..847bcb5d08eb3 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -86,7 +86,6 @@ import android.app.IUidObserver; import android.app.Notification; import android.app.PendingIntent; import android.app.usage.UsageStatsManagerInternal; -import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -154,7 +153,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.google.android.collect.Lists; @@ -182,8 +180,7 @@ import java.util.List; * and delivers to listeners, such as {@link ConnectivityManager}, for * enforcement. */ -public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub - implements AppIdleStateChangeListener { +public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final String TAG = "NetworkPolicy"; private static final boolean LOGD = false; private static final boolean LOGV = false; @@ -279,6 +276,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub final SparseIntArray mUidPolicy = new SparseIntArray(); /** Currently derived rules for each UID. */ final SparseIntArray mUidRules = new SparseIntArray(); + /** Set of states for the child firewall chains. True if the chain is active. */ final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); /** @@ -508,7 +506,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub WifiManager.NETWORK_STATE_CHANGED_ACTION); mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler); - mUsageStats.addAppIdleStateChangeListener(this); + mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener()); } @@ -2043,7 +2041,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub } setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules); } - enableFirewallChain(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode); + enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode); + } + + void updateRulesForAppIdleParoleLocked() { + boolean enableChain = !mUsageStats.isAppIdleParoleOn(); + enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain); } /** @@ -2187,9 +2190,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0; if (oldFirewallReject != firewallReject) { setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject); - if (mDeviceIdleMode && !firewallReject) { - // if we are in device idle mode, and we decide to allow this uid. we need to punch - // a hole in the device idle chain. + if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE) && !firewallReject) { + // if the dozable chain is on, and we decide to allow this uid. we need to punch + // a hole in the dozable chain. setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false); } } @@ -2207,15 +2210,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub } } - @Override - public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { - try { - int uid = mContext.getPackageManager().getPackageUid(packageName, userId); - synchronized (mRulesLock) { - updateRulesForUidLocked(uid); + private class AppIdleStateChangeListener + extends UsageStatsManagerInternal.AppIdleStateChangeListener { + + @Override + public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { + try { + int uid = mContext.getPackageManager().getPackageUid(packageName, userId); + synchronized (mRulesLock) { + updateRulesForUidLocked(uid); + } + } catch (NameNotFoundException nnfe) { + } + } + + @Override + public void onParoleStateChanged(boolean isParoleOn) { + synchronized (mRulesLock) { + updateRulesForAppIdleParoleLocked(); } - } catch (NameNotFoundException nnfe) { - return; } } @@ -2381,12 +2394,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub /** * Add or remove a uid to the firewall blacklist for all network ifaces. */ - private void enableFirewallChain(int chain, boolean enable) { + private void enableFirewallChainLocked(int chain, boolean enable) { if (mFirewallChainStates.indexOfKey(chain) >= 0 && mFirewallChainStates.get(chain) == enable) { // All is the same, nothing to do. return; } + mFirewallChainStates.put(chain, enable); try { mNetworkManager.setFirewallChainEnabled(chain, enable); } catch (IllegalStateException e) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 490236e41ac77..c49a5f95708f1 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -119,6 +119,7 @@ public class UsageStatsService extends SystemService implements static final int MSG_CHECK_PAROLE_TIMEOUT = 6; static final int MSG_PAROLE_END_TIMEOUT = 7; static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8; + static final int MSG_PAROLE_STATE_CHANGED = 9; private final Object mLock = new Object(); Handler mHandler; @@ -313,7 +314,7 @@ public class UsageStatsService extends SystemService implements mLastAppIdleParoledTime = checkAndGetTimeLocked(); postNextParoleTimeout(); } - postCheckIdleStates(UserHandle.USER_ALL); + postParoleStateChanged(); } } } @@ -338,6 +339,12 @@ public class UsageStatsService extends SystemService implements mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis); } + 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); + } + void postCheckIdleStates(int userId) { mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); } @@ -756,6 +763,13 @@ public class UsageStatsService extends SystemService implements } } + boolean isAppIdleFilteredOrParoled(String packageName, int userId, long timeNow) { + if (mAppIdleParoled) { + return false; + } + return isAppIdleFiltered(packageName, userId, timeNow); + } + boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { final UserUsageStatsService userService; final long screenOnTime; @@ -782,13 +796,6 @@ public class UsageStatsService extends SystemService implements if (!mAppIdleEnabled) { return false; } - synchronized (mLock) { - // Temporary exemption, probably due to device charging or occasional allowance to - // be allowed to sync, etc. - if (mAppIdleParoled) { - return false; - } - } if (packageName.equals("android")) return false; try { if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) { @@ -846,6 +853,12 @@ public class UsageStatsService extends SystemService implements } } + void informParoleStateChanged() { + for (AppIdleStateChangeListener listener : mPackageAccessListeners) { + listener.onParoleStateChanged(mAppIdleParoled); + } + } + private static boolean validRange(long currentTime, long beginTime, long endTime) { return beginTime <= currentTime && beginTime < endTime; } @@ -975,6 +988,11 @@ public class UsageStatsService extends SystemService implements args.recycle(); break; + case MSG_PAROLE_STATE_CHANGED: + if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled); + informParoleStateChanged(); + break; + default: super.handleMessage(msg); break; @@ -1126,7 +1144,7 @@ public class UsageStatsService extends SystemService implements } final long token = Binder.clearCallingIdentity(); try { - return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); + return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1); } finally { Binder.restoreCallingIdentity(token); } @@ -1250,6 +1268,11 @@ public class UsageStatsService extends SystemService implements return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); } + @Override + public boolean isAppIdleParoleOn() { + return mAppIdleParoled; + } + @Override public void prepareShutdown() { // This method *WILL* do IO work, but we must block until it is finished or else @@ -1261,6 +1284,7 @@ public class UsageStatsService extends SystemService implements @Override public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) { UsageStatsService.this.addListener(listener); + listener.onParoleStateChanged(isAppIdleParoleOn()); } @Override