More Data Saver / Battery Saver modes cleanup
When Battery Saver mode was first implemented, there were no firewall rules
on netd, so the solution was to make all network interface metered and
re-use the bw_penalty_box chain.
Recently, a fw_powersave chain was created with the purpose of
separating these 2 concerns, but some scenarios were no properly
handled.
This change further cleans up the code by:
- Creating a updateRestrictionRulesForUidLocked() to be used when both
Battery Saver and Power Save rules need to be re-evaluated.
- Renaming some methods to be more consistent with others.
- Disabling rules for apps that do not have internet permissions.
- Updating network stats only when process status changes.
- Only updating Battery Saver rules when they changed.
BUG: 27127112
BUG: 26685616
Change-Id: I75fbc9733b8989fadcb10ebc154e214e3d256fe9
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9b92e4f..c75e287 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -687,7 +687,7 @@
// global background data policy
if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
synchronized (mRulesLock) {
- updateRestrictDataRulesForUidLocked(uid);
+ updateRestrictionRulesForUidLocked(uid);
}
}
}
@@ -705,7 +705,7 @@
if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
synchronized (mRulesLock) {
mUidPolicy.delete(uid);
- updateRestrictDataRulesForUidLocked(uid);
+ updateRuleForRestrictBackgroundLocked(uid);
writePolicyLocked();
}
}
@@ -1678,7 +1678,7 @@
mUidPolicy.put(uid, policy);
// uid policy changed, recompute rules and persist policy.
- updateRestrictDataRulesForUidLocked(uid);
+ updateRuleForRestrictBackgroundLocked(uid);
if (persist) {
writePolicyLocked();
}
@@ -1897,7 +1897,7 @@
maybeRefreshTrustedTime();
synchronized (mRulesLock) {
mRestrictBackground = restrictBackground;
- updateRulesForRestrictDataLocked();
+ updateRulesForRestrictBackgroundLocked();
updateNotificationsLocked();
writePolicyLocked();
}
@@ -2272,7 +2272,7 @@
final int rule = mUidRules.get(uid, RULE_UNKNOWN);
fout.print(" rule=");
- fout.print(DebugUtils.valueToString(NetworkPolicyManager.class, "RULE_", rule));
+ fout.print(ruleToString(rule));
fout.println();
}
@@ -2280,6 +2280,10 @@
}
}
+ private String ruleToString(int rule) {
+ return DebugUtils.valueToString(NetworkPolicyManager.class, "RULE_", rule);
+ }
+
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) throws RemoteException {
@@ -2296,57 +2300,73 @@
}
}
- boolean isUidForegroundLocked(int uid) {
+ private boolean isUidForegroundLocked(int uid) {
+ return isUidStateForegroundLocked(
+ mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
+ }
+
+ private boolean isUidStateForegroundLocked(int state) {
// only really in foreground when screen is also on
- return mScreenOn && mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY)
- <= ActivityManager.PROCESS_STATE_TOP;
+ return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
}
/**
* Process state of UID changed; if needed, will trigger
* {@link #updateRestrictDataRulesForUidLocked(int)}.
*/
- void updateUidStateLocked(int uid, int uidState) {
+ private void updateUidStateLocked(int uid, int uidState) {
final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
if (oldUidState != uidState) {
// state changed, push updated rules
mUidState.put(uid, uidState);
- updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
+ updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);
if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
if (mDeviceIdleMode) {
updateRuleForDeviceIdleLocked(uid);
}
if (mRestrictPower) {
- updateRulesForRestrictPowerLocked(uid);
+ updateRuleForRestrictPowerLocked(uid);
}
}
+ updateNetworkStats(uid, isUidStateForegroundLocked(uidState));
}
}
- void removeUidStateLocked(int uid) {
+ private void removeUidStateLocked(int uid) {
final int index = mUidState.indexOfKey(uid);
if (index >= 0) {
final int oldUidState = mUidState.valueAt(index);
mUidState.removeAt(index);
if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
- updateRulesForUidStateChangeLocked(uid, oldUidState,
+ updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState,
ActivityManager.PROCESS_STATE_CACHED_EMPTY);
if (mDeviceIdleMode) {
updateRuleForDeviceIdleLocked(uid);
}
if (mRestrictPower) {
- updateRulesForRestrictPowerLocked(uid);
+ updateRuleForRestrictPowerLocked(uid);
}
+ updateNetworkStats(uid, false);
}
}
}
- void updateRulesForUidStateChangeLocked(int uid, int oldUidState, int newUidState) {
+ // adjust stats accounting based on foreground status
+ private void updateNetworkStats(int uid, boolean uidForeground) {
+ try {
+ mNetworkStats.setUidForeground(uid, uidForeground);
+ } catch (RemoteException e) {
+ // ignored; service lives in system_server
+ }
+ }
+
+ private void updateRestrictBackgroundRulesOnUidStatusChangedLocked(int uid, int oldUidState,
+ int newUidState) {
final boolean oldForeground = oldUidState <= ActivityManager.PROCESS_STATE_TOP;
final boolean newForeground = newUidState <= ActivityManager.PROCESS_STATE_TOP;
if (oldForeground != newForeground) {
- updateRestrictDataRulesForUidLocked(uid);
+ updateRuleForRestrictBackgroundLocked(uid);
}
}
@@ -2370,7 +2390,7 @@
for (int i = 0; i < size; i++) {
if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_TOP) {
final int uid = mUidState.keyAt(i);
- updateRestrictDataRulesForUidLocked(uid);
+ updateRestrictionRulesForUidLocked(uid);
}
}
}
@@ -2384,7 +2404,7 @@
mUidFirewallPowerSaveRules);
}
- void updateRulesForRestrictPowerLocked(int uid) {
+ void updateRuleForRestrictPowerLocked(int uid) {
updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
}
@@ -2397,8 +2417,8 @@
updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
}
- // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
- // for whitelisting, we can reuse their logic in this method.
+ // NOTE: since both fw_dozable and fw_powersave uses the same map
+ // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
SparseIntArray rules) {
if (enabled) {
@@ -2433,8 +2453,8 @@
enableFirewallChainLocked(chain, enabled);
}
- // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
- // for whitelisting, we can reuse their logic in this method.
+ // NOTE: since both fw_dozable and fw_powersave uses the same map
+ // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
if (enabled) {
int appId = UserHandle.getAppId(uid);
@@ -2452,7 +2472,6 @@
uidRules.clear();
// Fully update the app idle firewall chain.
- final IPackageManager ipm = AppGlobals.getPackageManager();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
UserInfo user = users.get(ui);
@@ -2499,7 +2518,7 @@
updateRulesForDeviceIdleLocked();
updateRulesForAppIdleLocked();
updateRulesForRestrictPowerLocked();
- updateRulesForRestrictDataLocked();
+ updateRulesForRestrictBackgroundLocked();
// If the set of restricted networks may have changed, re-evaluate those.
if (restrictedNetworksChanged) {
@@ -2513,7 +2532,7 @@
}
}
- private void updateRulesForRestrictDataLocked() {
+ private void updateRulesForRestrictBackgroundLocked() {
final PackageManager pm = mContext.getPackageManager();
// update rules for all installed applications
@@ -2530,13 +2549,13 @@
for (int j = 0; j < appsSize; j++) {
final ApplicationInfo app = apps.get(j);
final int uid = UserHandle.getUid(user.id, app.uid);
- updateRestrictDataRulesForUidLocked(uid);
+ updateRuleForRestrictBackgroundLocked(uid);
}
}
// limit data usage for some internal system services
- updateRestrictDataRulesForUidLocked(android.os.Process.MEDIA_UID);
- updateRestrictDataRulesForUidLocked(android.os.Process.DRM_UID);
+ updateRuleForRestrictBackgroundLocked(android.os.Process.MEDIA_UID);
+ updateRuleForRestrictBackgroundLocked(android.os.Process.DRM_UID);
}
private void updateRulesForTempWhitelistChangeLocked() {
@@ -2548,15 +2567,15 @@
int uid = UserHandle.getUid(user.id, appId);
updateRuleForAppIdleLocked(uid);
updateRuleForDeviceIdleLocked(uid);
- updateRulesForRestrictPowerLocked(uid);
+ updateRuleForRestrictPowerLocked(uid);
}
}
}
- private static boolean isUidValidForRules(int uid) {
- // allow rules on specific system services, and any apps
+ private boolean isUidValidForRules(int uid) {
+ // allow rules on specific system services, and any apps (that have network access)
if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
- || UserHandle.isApp(uid)) {
+ || (UserHandle.isApp(uid) && hasInternetPermissions(uid))) {
return true;
}
@@ -2594,12 +2613,21 @@
}
/**
- * Applies network rules to bandwidth controllers based on uid policy.
+ * Applies network rules to bandwidth and firewall controllers based on uid policy.
*
- * @param uid The uid for which to apply the latest policy
+ * <p>There are currently 2 types of restriction rules:
+ * <ul>
+ * <li>Battery Saver Mode (also referred as power save).
+ * <li>Data Saver Mode (formerly known as restrict background data).
+ * </ul>
*/
- private void updateRestrictDataRulesForUidLocked(int uid) {
- if (!isUidValidForRules(uid) || !hasInternetPermissions(uid)) return;
+ private void updateRestrictionRulesForUidLocked(int uid) {
+ updateRuleForRestrictPowerLocked(uid);
+ updateRuleForRestrictBackgroundLocked(uid);
+ }
+
+ private void updateRuleForRestrictBackgroundLocked(int uid) {
+ if (!isUidValidForRules(uid)) return;
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final boolean uidForeground = isUidForegroundLocked(uid);
@@ -2618,8 +2646,10 @@
}
final int oldRule = mUidRules.get(uid);
- if (LOGV) Log.v(TAG, "updateBandwithControllerRulesForUidLocked(" + uid + "): oldRule = "
- + oldRule + ", newRule = " + newRule);
+ if (LOGV) {
+ Log.v(TAG, "updateRulesForRestrictBackgroundLocked(" + uid + "): oldRule = "
+ + ruleToString(oldRule) + ", newRule = " + ruleToString(newRule));
+ }
if (newRule == RULE_ALLOW_ALL) {
mUidRules.delete(uid);
@@ -2627,20 +2657,14 @@
mUidRules.put(uid, newRule);
}
- final boolean rejectMetered = (newRule == RULE_REJECT_METERED);
- setUidNetworkRules(uid, rejectMetered);
-
- // dispatch changed rule to existing listeners
if (oldRule != newRule) {
+ final boolean rejectMetered = (newRule == RULE_REJECT_METERED);
+ setUidNetworkRules(uid, rejectMetered);
+
+ // dispatch changed rule to existing listeners
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newRule).sendToTarget();
}
- try {
- // adjust stats accounting based on foreground status
- mNetworkStats.setUidForeground(uid, uidForeground);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
}
private class AppIdleStateChangeListener