Merge "Fixed connectivity state in some power saving scenarios." into nyc-dev

This commit is contained in:
TreeHugger Robot
2016-05-13 17:14:11 +00:00
committed by Android (Google) Code Review
6 changed files with 174 additions and 156 deletions

View File

@@ -23,6 +23,5 @@ oneway interface INetworkPolicyListener {
void onMeteredIfacesChanged(in String[] meteredIfaces); void onMeteredIfacesChanged(in String[] meteredIfaces);
void onRestrictBackgroundChanged(boolean restrictBackground); void onRestrictBackgroundChanged(boolean restrictBackground);
void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted); void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted);
void onRestrictPowerChanged(boolean restrictPower);
} }

View File

@@ -54,7 +54,6 @@ interface INetworkPolicyManager {
/** Control if background data is restricted system-wide. */ /** Control if background data is restricted system-wide. */
void setRestrictBackground(boolean restrictBackground); void setRestrictBackground(boolean restrictBackground);
boolean getRestrictBackground(); boolean getRestrictBackground();
boolean getRestrictPower();
/** Callback used to change internal state on tethering */ /** Callback used to change internal state on tethering */
void onTetheringChanged(String iface, boolean tethering); void onTetheringChanged(String iface, boolean tethering);

View File

@@ -90,10 +90,6 @@ public class DataSaverController {
}); });
} }
@Override
public void onRestrictPowerChanged(boolean restrictPower) {
}
@Override @Override
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) { public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
} }

View File

@@ -33,6 +33,7 @@ import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS; import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS; import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED; import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.uidRulesToString; import static android.net.NetworkPolicyManager.uidRulesToString;
@@ -218,9 +219,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
/** Flag indicating if background data is restricted. */ /** Flag indicating if background data is restricted. */
@GuardedBy("mRulesLock") @GuardedBy("mRulesLock")
private boolean mRestrictBackground; private boolean mRestrictBackground;
/** Flag indicating if background data is restricted due to battery savings. */
@GuardedBy("mRulesLock")
private boolean mRestrictPower;
final private Context mContext; final private Context mContext;
private int mNetworkPreference; private int mNetworkPreference;
@@ -669,7 +667,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
try { try {
mPolicyManager.setConnectivityListener(mPolicyListener); mPolicyManager.setConnectivityListener(mPolicyListener);
mRestrictBackground = mPolicyManager.getRestrictBackground(); mRestrictBackground = mPolicyManager.getRestrictBackground();
mRestrictPower = mPolicyManager.getRestrictPower();
} catch (RemoteException e) { } catch (RemoteException e) {
// ouch, no rules updates means some processes may never get network // ouch, no rules updates means some processes may never get network
loge("unable to register INetworkPolicyListener" + e); loge("unable to register INetworkPolicyListener" + e);
@@ -942,13 +939,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
+ ": " + allowed); + ": " + allowed);
} }
} }
// ...then Battery Saver Mode. // ...then power restrictions.
if (allowed && mRestrictPower) { if (allowed) {
allowed = (uidRules & RULE_ALLOW_ALL) != 0; allowed = (uidRules & RULE_REJECT_ALL) == 0;
if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when" if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
+ " mRestrictPower=" + mRestrictPower + " rule is " + uidRulesToString(uidRules) + ": " + allowed);
+ ", whitelisted=" + ((uidRules & RULE_ALLOW_ALL) != 0)
+ ": " + allowed);
} }
return !allowed; return !allowed;
} }
@@ -1400,8 +1395,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int oldRules = mUidRules.get(uid, RULE_NONE); final int oldRules = mUidRules.get(uid, RULE_NONE);
if (oldRules == uidRules) return; if (oldRules == uidRules) return;
if (uidRules == RULE_NONE) {
mUidRules.delete(uid);
} else {
mUidRules.put(uid, uidRules); mUidRules.put(uid, uidRules);
} }
}
// TODO: notify UID when it has requested targeted updates // TODO: notify UID when it has requested targeted updates
} }
@@ -1438,18 +1437,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
@Override
public void onRestrictPowerChanged(boolean restrictPower) {
// caller is NPMS, since we only register with them
if (LOGD_RULES) {
log("onRestrictPowerChanged(restrictPower=" + restrictPower + ")");
}
synchronized (mRulesLock) {
mRestrictPower = restrictPower;
}
}
@Override @Override
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) { public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
if (LOGD_RULES) { if (LOGD_RULES) {
@@ -1891,10 +1878,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println(mRestrictBackground); pw.println(mRestrictBackground);
pw.println(); pw.println();
pw.print("Restrict power: ");
pw.println(mRestrictPower);
pw.println();
pw.println("Status for known UIDs:"); pw.println("Status for known UIDs:");
pw.increaseIndent(); pw.increaseIndent();
final int size = mUidRules.size(); final int size = mUidRules.size();

View File

@@ -169,11 +169,6 @@ public class ConnectivityController extends StateController implements
updateTrackedJobs(-1); updateTrackedJobs(-1);
} }
@Override
public void onRestrictPowerChanged(boolean restrictPower) {
updateTrackedJobs(-1);
}
@Override @Override
public void onRestrictBackgroundChanged(boolean restrictBackground) { public void onRestrictBackgroundChanged(boolean restrictBackground) {
updateTrackedJobs(-1); updateTrackedJobs(-1);

View File

@@ -266,7 +266,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9; private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
private static final int MSG_UPDATE_INTERFACE_QUOTA = 10; private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
private static final int MSG_REMOVE_INTERFACE_QUOTA = 11; private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
private static final int MSG_RESTRICT_POWER_CHANGED = 12;
private final Context mContext; private final Context mContext;
private final IActivityManager mActivityManager; private final IActivityManager mActivityManager;
@@ -557,18 +556,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
updateRulesForGlobalChangeLocked(true); updateRulesForGlobalChangeLocked(true);
} }
} }
mHandler.obtainMessage(MSG_RESTRICT_POWER_CHANGED,
enabled ? 1 : 0, 0).sendToTarget();
} }
}); });
final boolean oldRestrictPower = mRestrictPower;
mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled(); mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
if (mRestrictPower != oldRestrictPower) {
// Some early services may have read the default value,
// so notify them that it's changed
mHandler.obtainMessage(MSG_RESTRICT_POWER_CHANGED,
mRestrictPower ? 1 : 0, 0).sendToTarget();
}
mSystemReady = true; mSystemReady = true;
@@ -740,7 +730,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid); if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
synchronized (mRulesLock) { synchronized (mRulesLock) {
mUidPolicy.delete(uid); mUidPolicy.delete(uid);
updateRuleForRestrictBackgroundLocked(uid); updateRestrictionRulesForUidLocked(uid);
writePolicyLocked(); writePolicyLocked();
} }
} }
@@ -1729,7 +1719,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUidPolicy.put(uid, policy); mUidPolicy.put(uid, policy);
// uid policy changed, recompute rules and persist policy. // uid policy changed, recompute rules and persist policy.
updateRuleForRestrictBackgroundLocked(uid); updateRulesForDataUsageRestrictionsLocked(uid);
if (persist) { if (persist) {
writePolicyLocked(); writePolicyLocked();
} }
@@ -2036,7 +2026,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
if (needFirewallRules) { if (needFirewallRules) {
// Only update firewall rules if necessary... // Only update firewall rules if necessary...
updateRuleForRestrictBackgroundLocked(uid); updateRulesForDataUsageRestrictionsLocked(uid);
} }
// ...but always persists the whitelist request. // ...but always persists the whitelist request.
writePolicyLocked(); writePolicyLocked();
@@ -2081,7 +2071,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
if (needFirewallRules) { if (needFirewallRules) {
// Only update firewall rules if necessary... // Only update firewall rules if necessary...
updateRuleForRestrictBackgroundLocked(uid, uidDeleted); updateRulesForDataUsageRestrictionsLocked(uid, uidDeleted);
} }
if (updateNow) { if (updateNow) {
// ...but always persists the whitelist request. // ...but always persists the whitelist request.
@@ -2145,15 +2135,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
} }
@Override
public boolean getRestrictPower() {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
synchronized (mRulesLock) {
return mRestrictPower;
}
}
@Override @Override
public void setDeviceIdleMode(boolean enabled) { public void setDeviceIdleMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
@@ -2446,6 +2427,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return isProcStateAllowedWhileOnRestrictBackgroundLocked(procState); return isProcStateAllowedWhileOnRestrictBackgroundLocked(procState);
} }
private boolean isUidForegroundOnRestrictPowerLocked(int uid) {
final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
return isProcStateAllowedWhileIdleOrPowerSaveMode(procState);
}
private boolean isUidStateForegroundLocked(int state) { private boolean isUidStateForegroundLocked(int state) {
// only really in foreground when screen is also on // only really in foreground when screen is also on
return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP; return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
@@ -2453,7 +2439,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** /**
* Process state of UID changed; if needed, will trigger * Process state of UID changed; if needed, will trigger
* {@link #updateRuleForRestrictBackgroundLocked(int)}. * {@link #updateRulesForDataUsageRestrictionsLocked(int)} and
* {@link #updateRulesForPowerRestrictionsLocked(int)}
*/ */
private void updateUidStateLocked(int uid, int uidState) { private void updateUidStateLocked(int uid, int uidState) {
final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
@@ -2463,12 +2450,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState); updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);
if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState) if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) { != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
if (isUidIdle(uid)) {
updateRuleForAppIdleLocked(uid);
}
if (mDeviceIdleMode) { if (mDeviceIdleMode) {
updateRuleForDeviceIdleLocked(uid); updateRuleForDeviceIdleLocked(uid);
} }
if (mRestrictPower) { if (mRestrictPower) {
updateRuleForRestrictPowerLocked(uid); updateRuleForRestrictPowerLocked(uid);
} }
updateRulesForPowerRestrictionsLocked(uid);
} }
updateNetworkStats(uid, isUidStateForegroundLocked(uidState)); updateNetworkStats(uid, isUidStateForegroundLocked(uidState));
} }
@@ -2488,6 +2479,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (mRestrictPower) { if (mRestrictPower) {
updateRuleForRestrictPowerLocked(uid); updateRuleForRestrictPowerLocked(uid);
} }
updateRulesForPowerRestrictionsLocked(uid);
updateNetworkStats(uid, false); updateNetworkStats(uid, false);
} }
} }
@@ -2509,7 +2501,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean newForeground = final boolean newForeground =
isProcStateAllowedWhileOnRestrictBackgroundLocked(newUidState); isProcStateAllowedWhileOnRestrictBackgroundLocked(newUidState);
if (oldForeground != newForeground) { if (oldForeground != newForeground) {
updateRuleForRestrictBackgroundLocked(uid); updateRulesForDataUsageRestrictionsLocked(uid);
} }
} }
@@ -2600,6 +2592,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
enableFirewallChainLocked(chain, enabled); enableFirewallChainLocked(chain, enabled);
} }
private void updateRulesForNonMeteredNetworksLocked() {
}
private boolean isWhitelistedBatterySaverLocked(int uid) { private boolean isWhitelistedBatterySaverLocked(int uid) {
final int appId = UserHandle.getAppId(uid); final int appId = UserHandle.getAppId(uid);
return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId); return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId);
@@ -2646,7 +2642,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (!isUidValidForBlacklistRules(uid)) return; if (!isUidValidForBlacklistRules(uid)) return;
int appId = UserHandle.getAppId(uid); int appId = UserHandle.getAppId(uid);
if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)) { if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
&& !isUidForegroundOnRestrictPowerLocked(uid)) {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY); setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
} else { } else {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT); setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
@@ -2701,7 +2698,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (int j = 0; j < appsSize; j++) { for (int j = 0; j < appsSize; j++) {
final ApplicationInfo app = apps.get(j); final ApplicationInfo app = apps.get(j);
final int uid = UserHandle.getUid(user.id, app.uid); final int uid = UserHandle.getUid(user.id, app.uid);
updateRuleForRestrictBackgroundLocked(uid); updateRulesForDataUsageRestrictionsLocked(uid);
updateRulesForPowerRestrictionsLocked(uid);
} }
} }
} }
@@ -2713,9 +2711,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) { for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
int appId = mPowerSaveTempWhitelistAppIds.keyAt(j); int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
int uid = UserHandle.getUid(user.id, appId); int uid = UserHandle.getUid(user.id, appId);
// Update external firewall rules.
updateRuleForAppIdleLocked(uid); updateRuleForAppIdleLocked(uid);
updateRuleForDeviceIdleLocked(uid); updateRuleForDeviceIdleLocked(uid);
updateRuleForRestrictPowerLocked(uid); updateRuleForRestrictPowerLocked(uid);
// Update internal rules.
updateRulesForPowerRestrictionsLocked(uid);
} }
} }
} }
@@ -2769,15 +2770,27 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** /**
* Applies network rules to bandwidth and firewall controllers based on uid policy. * Applies network rules to bandwidth and firewall controllers based on uid policy.
* *
* <p>There are currently 2 types of restriction rules: * <p>There are currently 4 types of restriction rules:
* <ul> * <ul>
* <li>Doze mode
* <li>App idle mode
* <li>Battery Saver Mode (also referred as power save). * <li>Battery Saver Mode (also referred as power save).
* <li>Data Saver Mode (The Feature Formerly Known As 'Restrict Background Data'). * <li>Data Saver Mode (The Feature Formerly Known As 'Restrict Background Data').
* </ul> * </ul>
*
* <p>This method changes both the external firewall rules and the internal state.
*/ */
private void updateRestrictionRulesForUidLocked(int uid) { private void updateRestrictionRulesForUidLocked(int uid) {
// Methods below only changes the firewall rules for the power-related modes.
updateRuleForDeviceIdleLocked(uid);
updateRuleForAppIdleLocked(uid);
updateRuleForRestrictPowerLocked(uid); updateRuleForRestrictPowerLocked(uid);
updateRuleForRestrictBackgroundLocked(uid);
// Update internal state for power-related modes.
updateRulesForPowerRestrictionsLocked(uid);
// Update firewall and internal rules for Data Saver Mode.
updateRulesForDataUsageRestrictionsLocked(uid);
} }
/** /**
@@ -2799,7 +2812,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} / * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
* {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist * {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
* respectively): these methods set the proper internal state (blacklist / whitelist), then call * respectively): these methods set the proper internal state (blacklist / whitelist), then call
* this ({@link #updateRuleForRestrictBackgroundLocked(int)}) to propagate the rules to * this ({@link #updateRulesForDataUsageRestrictionsLocked(int)}) to propagate the rules to
* {@link INetworkManagementService}, but this method should also be called in events (like * {@link INetworkManagementService}, but this method should also be called in events (like
* Data Saver Mode flips or UID state changes) that might affect the foreground app, since the * Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
* following rules should also be applied: * following rules should also be applied:
@@ -2818,19 +2831,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* *
* <p>The {@link #mUidRules} map is used to define the transtion of states of an UID. * <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
* *
* <p>This method also updates the {@link #mUidRules} with the power-related status for the uid
* and send the proper {@value #MSG_RULES_CHANGED} notification, although it does not change
* the power-related firewall rules per se.
*/ */
private void updateRuleForRestrictBackgroundLocked(int uid) { private void updateRulesForDataUsageRestrictionsLocked(int uid) {
updateRuleForRestrictBackgroundLocked(uid, false); updateRulesForDataUsageRestrictionsLocked(uid, false);
} }
/** /**
* Overloaded version of {@link #updateRuleForRestrictBackgroundLocked(int)} called when an * Overloaded version of {@link #updateRulesForDataUsageRestrictionsLocked(int)} called when an
* app is removed - it ignores the UID validity check. * app is removed - it ignores the UID validity check.
*/ */
private void updateRuleForRestrictBackgroundLocked(int uid, boolean uidDeleted) { private void updateRulesForDataUsageRestrictionsLocked(int uid, boolean uidDeleted) {
if (!uidDeleted && !isUidValidForWhitelistRules(uid)) { if (!uidDeleted && !isUidValidForWhitelistRules(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid); if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
return; return;
@@ -2840,50 +2850,36 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int oldUidRules = mUidRules.get(uid, RULE_NONE); final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid); final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);
// Data Saver status. final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
final boolean isDsBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
final boolean isDsWhitelisted = mRestrictBackgroundWhitelistUids.get(uid); final int oldRule = oldUidRules & MASK_METERED_NETWORKS;
final int oldDsRule = oldUidRules & MASK_METERED_NETWORKS; int newRule = RULE_NONE;
int newDsRule = RULE_NONE;
// Battery Saver status.
final boolean isBsWhitelisted = isWhitelistedBatterySaverLocked(uid);
final int oldBsRule = oldUidRules & MASK_ALL_NETWORKS;
int newBsRule = RULE_NONE;
// First step: define the new rule based on user restrictions and foreground state. // First step: define the new rule based on user restrictions and foreground state.
if (isForeground) { if (isForeground) {
// Data Saver rules if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
if (isDsBlacklisted || (mRestrictBackground && !isDsWhitelisted)) { newRule = RULE_TEMPORARY_ALLOW_METERED;
newDsRule = RULE_TEMPORARY_ALLOW_METERED; } else if (isWhitelisted) {
} else if (isDsWhitelisted) { newRule = RULE_ALLOW_METERED;
newDsRule = RULE_ALLOW_METERED;
}
// Battery Saver rules
if (mRestrictPower) {
newBsRule = RULE_ALLOW_ALL;
} }
} else { } else {
// Data Saver rules if (isBlacklisted) {
if (isDsBlacklisted) { newRule = RULE_REJECT_METERED;
newDsRule = RULE_REJECT_METERED; } else if (mRestrictBackground && isWhitelisted) {
} else if (mRestrictBackground && isDsWhitelisted) { newRule = RULE_ALLOW_METERED;
newDsRule = RULE_ALLOW_METERED;
}
// Battery Saver rules
if (mRestrictPower) {
newBsRule = isBsWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
} }
} }
final int newUidRules = newDsRule | newBsRule; final int newUidRules = newRule | (oldUidRules & MASK_ALL_NETWORKS);
if (LOGV) { if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + "):" Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + ")"
+ " isForeground=" +isForeground + ", isBlacklisted: " + isDsBlacklisted + ": isForeground=" +isForeground
+ ", isDsWhitelisted: " + isDsWhitelisted + ", isBlacklisted=" + isBlacklisted
+ ", isBsWhitelisted: " + isBsWhitelisted + ", isWhitelisted=" + isWhitelisted
+ ", newUidRules: " + uidRulesToString(newUidRules) + ", oldRule=" + uidRulesToString(oldRule)
+ ", oldUidRules: " + uidRulesToString(oldUidRules)); + ", newRule=" + uidRulesToString(newRule)
+ ", newUidRules=" + uidRulesToString(newUidRules)
+ ", oldUidRules=" + uidRulesToString(oldUidRules));
} }
if (newUidRules == RULE_NONE) { if (newUidRules == RULE_NONE) {
@@ -2895,12 +2891,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
boolean changed = false; boolean changed = false;
// Second step: apply bw changes based on change of state. // Second step: apply bw changes based on change of state.
if (newRule != oldRule) {
// Apply Data Saver rules.
if (newDsRule != oldDsRule) {
changed = true; changed = true;
if ((newDsRule & RULE_TEMPORARY_ALLOW_METERED) != 0) { if ((newRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
// Temporarily whitelist foreground app, removing from blacklist if necessary // Temporarily whitelist foreground app, removing from blacklist if necessary
// (since bw_penalty_box prevails over bw_happy_box). // (since bw_penalty_box prevails over bw_happy_box).
@@ -2908,68 +2902,132 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// TODO: if statement below is used to avoid an unnecessary call to netd / iptables, // TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
// but ideally it should be just: // but ideally it should be just:
// setMeteredNetworkBlacklist(uid, isBlacklisted); // setMeteredNetworkBlacklist(uid, isBlacklisted);
if (isDsBlacklisted) { if (isBlacklisted) {
setMeteredNetworkBlacklist(uid, false); setMeteredNetworkBlacklist(uid, false);
} }
} else if ((oldDsRule & RULE_TEMPORARY_ALLOW_METERED) != 0) { } else if ((oldRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
// Remove temporary whitelist from app that is not on foreground anymore. // Remove temporary whitelist from app that is not on foreground anymore.
// TODO: if statements below are used to avoid unnecessary calls to netd / iptables, // TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
// but ideally they should be just: // but ideally they should be just:
// setMeteredNetworkWhitelist(uid, isWhitelisted); // setMeteredNetworkWhitelist(uid, isWhitelisted);
// setMeteredNetworkBlacklist(uid, isBlacklisted); // setMeteredNetworkBlacklist(uid, isBlacklisted);
if (!isDsWhitelisted) { if (!isWhitelisted) {
setMeteredNetworkWhitelist(uid, false); setMeteredNetworkWhitelist(uid, false);
} }
if (isDsBlacklisted) { if (isBlacklisted) {
setMeteredNetworkBlacklist(uid, true); setMeteredNetworkBlacklist(uid, true);
} }
} else if ((newDsRule & RULE_REJECT_METERED) != 0 } else if ((newRule & RULE_REJECT_METERED) != 0
|| (oldDsRule & RULE_REJECT_METERED) != 0) { || (oldRule & RULE_REJECT_METERED) != 0) {
// Flip state because app was explicitly added or removed to blacklist. // Flip state because app was explicitly added or removed to blacklist.
setMeteredNetworkBlacklist(uid, isDsBlacklisted); setMeteredNetworkBlacklist(uid, isBlacklisted);
if ((oldDsRule & RULE_REJECT_METERED) != 0 && isDsWhitelisted) { if ((oldRule & RULE_REJECT_METERED) != 0 && isWhitelisted) {
// Since blacklist prevails over whitelist, we need to handle the special case // Since blacklist prevails over whitelist, we need to handle the special case
// where app is whitelisted and blacklisted at the same time (although such // where app is whitelisted and blacklisted at the same time (although such
// scenario should be blocked by the UI), then blacklist is removed. // scenario should be blocked by the UI), then blacklist is removed.
setMeteredNetworkWhitelist(uid, isDsWhitelisted); setMeteredNetworkWhitelist(uid, isWhitelisted);
} }
} else if ((newDsRule & RULE_ALLOW_METERED) != 0 } else if ((newRule & RULE_ALLOW_METERED) != 0
|| (oldDsRule & RULE_ALLOW_METERED) != 0) { || (oldRule & RULE_ALLOW_METERED) != 0) {
// Flip state because app was explicitly added or removed to whitelist. // Flip state because app was explicitly added or removed to whitelist.
setMeteredNetworkWhitelist(uid, isDsWhitelisted); setMeteredNetworkWhitelist(uid, isWhitelisted);
} else { } else {
// All scenarios should have been covered above // All scenarios should have been covered above.
Log.wtf(TAG, "Unexpected change of metered UID state for " + uid Log.wtf(TAG, "Unexpected change of metered UID state for " + uid
+ ": foreground=" + isForeground + ": foreground=" + isForeground
+ ", whitelisted=" + isDsWhitelisted + ", whitelisted=" + isWhitelisted
+ ", blacklisted=" + isDsBlacklisted + ", blacklisted=" + isBlacklisted
+ ", newRule=" + uidRulesToString(newUidRules) + ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules)); + ", oldRule=" + uidRulesToString(oldUidRules));
} }
// Dispatch changed rule to existing listeners.
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
}
} }
// Apply Battery Saver rules. /**
// NOTE: the firewall rules are changed outside this method, but it's still necessary to * Updates the power-related part of the {@link #mUidRules} for a given map, and notify external
// send the MSG_RULES_CHANGED so ConnectivityService can update its internal status. * listeners in case of change.
if (newBsRule != oldBsRule) { * <p>
changed = true; * There are 3 power-related rules that affects whether an app has background access on
if (newBsRule == RULE_NONE || (newBsRule & RULE_ALLOW_ALL) != 0) { * non-metered networks, and when the condition applies and the UID is not whitelisted for power
* restriction, it's added to the equivalent firewall chain:
* <ul>
* <li>App is idle: {@code fw_standby} firewall chain.
* <li>Device is idle: {@code fw_dozable} firewall chain.
* <li>Battery Saver Mode is on: {@code fw_powersave} firewall chain.
* </ul>
* <p>
* This method updates the power-related part of the {@link #mUidRules} for a given uid based on
* these modes, the UID process state (foreground or not), and the UIDwhitelist state.
* <p>
* <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
*/
private void updateRulesForPowerRestrictionsLocked(int uid) {
if (!isUidValidForBlacklistRules(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
return;
}
final boolean isIdle = isUidIdle(uid);
final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictPowerLocked(uid);
final boolean isWhitelisted = isWhitelistedBatterySaverLocked(uid);
final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
int newRule = RULE_NONE;
// First step: define the new rule based on user restrictions and foreground state.
// NOTE: if statements below could be inlined, but it's easier to understand the logic
// by considering the foreground and non-foreground states.
if (isForeground) {
if (restrictMode) {
newRule = RULE_ALLOW_ALL;
}
} else if (restrictMode) {
newRule = isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
}
final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
if (LOGV) {
Log.v(TAG, "updateRulesForNonMeteredNetworksLocked(" + uid + ")"
+ ", isIdle: " + isIdle
+ ", mRestrictPower: " + mRestrictPower
+ ", mDeviceIdleMode: " + mDeviceIdleMode
+ ", isForeground=" + isForeground
+ ", isWhitelisted=" + isWhitelisted
+ ", oldRule=" + uidRulesToString(oldRule)
+ ", newRule=" + uidRulesToString(newRule)
+ ", newUidRules=" + uidRulesToString(newUidRules)
+ ", oldUidRules=" + uidRulesToString(oldUidRules));
}
if (newUidRules == RULE_NONE) {
mUidRules.delete(uid);
} else {
mUidRules.put(uid, newUidRules);
}
// Second step: notify listeners if state changed.
if (newRule != oldRule) {
if (newRule == RULE_NONE || (newRule & RULE_ALLOW_ALL) != 0) {
if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid); if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid);
} else if ((newBsRule & RULE_REJECT_ALL) != 0) { } else if ((newRule & RULE_REJECT_ALL) != 0) {
if (LOGV) Log.v(TAG, "Rejecting non-metered access for UID " + uid); if (LOGV) Log.v(TAG, "Rejecting non-metered access for UID " + uid);
} else { } else {
// All scenarios should have been covered above // All scenarios should have been covered above
Log.wtf(TAG, "Unexpected change of non-metered UID state for " + uid Log.wtf(TAG, "Unexpected change of non-metered UID state for " + uid
+ ": foreground=" + isForeground + ": foreground=" + isForeground
+ ", whitelisted=" + isBsWhitelisted + ", whitelisted=" + isWhitelisted
+ ", newRule=" + uidRulesToString(newUidRules) + ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules)); + ", oldRule=" + uidRulesToString(oldUidRules));
} }
}
// Final step: dispatch changed rule to existing listeners
if (changed) {
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget(); mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
} }
} }
@@ -2982,8 +3040,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
try { try {
final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
if (LOGV) Log.v(TAG, "onAppIdleStateChanged(): uid=" + uid + ", idle=" + idle);
synchronized (mRulesLock) { synchronized (mRulesLock) {
updateRuleForAppIdleLocked(uid); updateRuleForAppIdleLocked(uid);
updateRulesForPowerRestrictionsLocked(uid);
} }
} catch (NameNotFoundException nnfe) { } catch (NameNotFoundException nnfe) {
} }
@@ -3036,16 +3096,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
} }
private void dispatchRestrictPowerChanged(INetworkPolicyListener listener,
boolean restrictPower) {
if (listener != null) {
try {
listener.onRestrictPowerChanged(restrictPower);
} catch (RemoteException ignored) {
}
}
}
private Handler.Callback mHandlerCallback = new Handler.Callback() { private Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override @Override
public boolean handleMessage(Message msg) { public boolean handleMessage(Message msg) {
@@ -3093,11 +3143,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} }
return true; return true;
} }
case MSG_RESTRICT_POWER_CHANGED: {
final boolean restrictPower = msg.arg1 != 0;
dispatchRestrictPowerChanged(mConnectivityListener, restrictPower);
return true;
}
case MSG_RESTRICT_BACKGROUND_CHANGED: { case MSG_RESTRICT_BACKGROUND_CHANGED: {
final boolean restrictBackground = msg.arg1 != 0; final boolean restrictBackground = msg.arg1 != 0;
dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground); dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
@@ -3410,6 +3455,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) Slog.v(TAG, "onPackageRemoved: " + packageName + " ->" + uid); if (LOGV) Slog.v(TAG, "onPackageRemoved: " + packageName + " ->" + uid);
synchronized (mRulesLock) { synchronized (mRulesLock) {
removeRestrictBackgroundWhitelistedUidLocked(uid, true, true); removeRestrictBackgroundWhitelistedUidLocked(uid, true, true);
updateRestrictionRulesForUidLocked(uid);
} }
} }
} }